C#のラムダ式にもクロージャがありますが、C#コミュニティや書籍ではほとんど議論されていません。JavaScriptの人々や本は、C#の世界よりも多くのJavaScriptの閉鎖について語っています。何故ですか?
C#のラムダ式にもクロージャがありますが、C#コミュニティや書籍ではほとんど議論されていません。JavaScriptの人々や本は、C#の世界よりも多くのJavaScriptの閉鎖について語っています。何故ですか?
回答:
javascriptには名前空間のような機能がないため、あらゆる種類のグローバルオブジェクトを簡単に台無しにすることができます。
そのため、独自の実行環境でいくつかのコードを分離できることが重要です。閉鎖はそのために最適です。
このようなクロージャーの使用は、コードを分離し、すべてをグローバルスコープに入れない名前空間やクラスなどがあるC#のような言語では意味がありません。
JavaScriptコードの非常に一般的な方法は、次のように記述することです。
(function(){
// Some code
})();
ご覧のとおり、これは匿名関数宣言であり、すぐに実行されます。したがって、関数内で定義されたすべてのものは、外部からアクセスすることは不可能であり、グローバルスコープを台無しにすることはありません。この関数の実行コンテキストは、このコンテキスト内で定義されたネストされた関数のように、コールバックなど何でも渡すことができるコードがある限り、存続します。
JavascriptはC#とは非常に異なる言語です。オブジェクト指向ではなく、プロトタイプ指向です。これは最後に非常に異なる慣行につながります。
とにかく、クロージャーは良いので、C#でも使用してください!
編集:stackoverflowのチャットでいくつか議論した後、私はこの答えを正確にする必要があると思います。
サンプルコードの関数はクロージャではありません。ただし、この関数はローカル変数とネストされた関数を定義できます。これらのローカル変数を使用するネストされた関数はすべてクロージャーです。
これは、グローバルスコープを台無しにすることなく、一連の関数間で一部のデータを共有するのに役立ちます。これは、javascriptでのクロージャーの最も一般的な使用法です。
クロージャーは、このようなデータを単に共有するよりもはるかに強力ですが、現実的に考えてみましょう。ほとんどのプログラマーは、関数型プログラミングに関することを知りません。C#では、この種の使用のためにクラスまたは名前空間を使用していましたが、JSはこの機能を提供しません。
グローバルスコープを保護するだけでなく、クロージャーを使用してより多くの方法を実行できますが、これはJSソースコードで見ることができます。
おそらく、JavaScriptのオブジェクト指向の一般的な実装はクロージャーに依存しているためでしょう。簡単な例を見てみましょう:
function counter() {
var value = 0;
this.getValue = function() { return value; }
this.increase = function() { value++; }
}
var myCounter = new counter();
console.log(myCounter.getValue());
myCounter.increase();
console.log(myCounter.getValue());
メソッドgetValue
とincrease
は、実際にはクロージャーであり、変数をカプセル化しますvalue
。
JavaScriptを「耐えられる」ものにするライブラリの多くがそれらを使用しているためです。
見てくださいjQueryの、プロトタイプやMooToolsのが名前だけの人気3に、。これらの各ライブラリはeach
、イテレータ関数を使用する好ましい反復方法として、コレクションのメソッドを提供します。その関数は、外部スコープの値にアクセスするときにクロージャーになります。
[1,2,3].each(function(item) {
console.log(item);
});
Ajaxでのコールバック、Ext.jsでのイベント処理などはすべて関数を使用します。一度だけ呼び出される100種類の関数でコードを肥大化させたくない場合は、クロージャーが最適です。
console.log
は外部スコープでconsole
定義されているため、「自由変数」も同様です。そして、実際には、何も変わらないforループであり、悪い習慣なのはなぜですか?
JavaScriptでの「良い」コーディングはクロージャーに大きく依存しているという他の回答にも同意します。ただし、それに加えて、おそらく各言語でこの機能がどのくらい使用されているかという問題にすぎません。JavaScriptには、最初の実装以来基本的にクロージャがあります。一方、C#には、Visual Studio 2008でリリースされた3.0以降のバージョンしかありません。
私が遭遇した多くのC#プログラマーは、まだ2.0プロジェクトに取り組んでいます。また、3.0または4.0で動作している場合でも、多くの場合2.0イディオムを使用しています。私は閉鎖が大好きです。概念がC#開発者の間で広まるにつれて、C#でより頻繁に使用されるようになります。
主な理由は、C#が静的に型指定されており、関数が単一の事前定義された環境にしかアクセスできないため、クロージャーの有用性が妨げられているためです。
一方、JavaScriptでは、クロージャーを使用すると、オブジェクトプロパティとしてアクセスし、ファーストクラスオブジェクトである場合、関数をメソッドとして動作させることができます。また、関数を異なる環境に挿入して、サブルーチンを異なるコンテキストで動作させることもできます。
私がそれらについて学ばなければならなかった理由の1つは、DOM要素(または実際に何か)をループしているときに、変数スコープを「クローズ」または「カプセル化」できるようにすることです。ここに投稿された例のように:https : //stackoverflow.com/questions/5606059/how-to-create-closure-in-loop-and-store-it-in-variable-for-later-execution