JavaScriptで閉鎖が重要なのはなぜですか?


16

C#のラムダ式にもクロージャがありますが、C#コミュニティや書籍ではほとんど議論されていません。JavaScriptの人々や本は、C#の世界よりも多くのJavaScriptの閉鎖について語っています。何故ですか?


3
JavaScriptは一流の関数型言語として扱われ、C#は古典的なOOP言語であるためです。異なるパラダイム、異なるプログラミングスタイル。
レイノス

1
ファーストクラスの機能を持つことは、言語を機能的な言語にします。PHP(5.3以降)、python、またはDにはファーストクラスの機能があります。それらは関数型言語であると言えますか?確かにそうではなく、JavaScriptもそうです。
deadalnix

1
@deadalnix JavaScriptはマルチパラダイム言語です。主に手続き型、機能型、およびプロトタイプのオブジェクト指向パラダイムをサポートします。決して純粋な関数型言語ではありませんが、言語を曲げることなく関数型パラダイムで簡単にJavaScriptを書くことができます。私はC#とPythonの同じことを言うでしょう。
レイノス

3
@ deadalnix、Yコンビネータを定義できる言語は関数型言語です。定義により。
SKロジック

1
@deadalnix:それは、どのアプローチが言語によって促進されているのかという問題だと思います。多くのJavaScriptフレームワークとプラットフォーム(特にnode.jsとDOM(イベントモデル))は、一次関数に大きく依存しています。PHPには、まったく同じプログラミングスタイルを可能にする機能がありますが、標準APIまたは多くのフレームワークを見ると、実際には言語の中核ではないことがわかります。
back2dos

回答:


5

javascriptには名前空間のような機能がないため、あらゆる種類のグローバルオブジェクトを簡単に台無しにすることができます。

そのため、独自の実行環境でいくつかのコードを分離できることが重要です。閉鎖はそのために最適です。

このようなクロージャーの使用は、コードを分離し、すべてをグローバルスコープに入れない名前空間やクラスなどがあるC#のような言語では意味がありません。

JavaScriptコードの非常に一般的な方法は、次のように記述することです。

(function(){
    // Some code
})();

ご覧のとおり、これは匿名関数宣言であり、すぐに実行されます。したがって、関数内で定義されたすべてのものは、外部からアクセスすることは不可能であり、グローバルスコープを台無しにすることはありません。この関数の実行コンテキストは、このコンテキスト内で定義されたネストされた関数のように、コールバックなど何でも渡すことができるコードがある限り、存続します。

JavascriptはC#とは非常に異なる言語です。オブジェクト指向ではなく、プロトタイプ指向です。これは最後に非常に異なる慣行につながります。

とにかく、クロージャーは良いので、C#でも使用してください!

編集:stackoverflowのチャットでいくつか議論した後、私はこの答えを正確にする必要があると思います。

サンプルコードの関数はクロージャではありません。ただし、この関数はローカル変数とネストされた関数を定義できます。これらのローカル変数を使用するネストされた関数はすべてクロージャーです。

これは、グローバルスコープを台無しにすることなく、一連の関数間で一部のデータを共有するのに役立ちます。これは、javascriptでのクロージャーの最も一般的な使用法です。

クロージャーは、このようなデータを単に共有するよりもはるかに強力ですが、現実的に考えてみましょう。ほとんどのプログラマーは、関数型プログラミングに関することを知りません。C#では、この種の使用のためにクラスまたは名前空間を使用していましたが、JSはこの機能を提供しません。

グローバルスコープを保護するだけでなく、クロージャーを使用してより多くの方法を実行できますが、これはJSソースコードで見ることができます。


9
それは閉鎖ではありません。関数を使用してローカルスコープを作成する利点を説明します。
レイノス

2
クロージャーは、フリー変数をクローズする場合にのみクロージャーです。また、JavaScriptの仕組みがわからないことを教えてくれてありがとう:)
Raynos

2
むしろ、私を初心者と呼ぶことで私を弱体化させることに頼るのではなく、JavaScript SOチャットルームで実際の議論を自由に進めてください。この議論は実際ここに属していませんが、SOチャットであ​​なたの誤解を喜んで議論します。
レイノス

1
ダウン投票。JavaScriptはオブジェクト指向です。クラスベースではありませんが、そのような機能は簡単に作成できます。ファーストクラスの機能を持ち、クロージャーを利用してイベント駆動型のパラダイムに自然に適合させます。著者であるBrendan Eichによると、インスピレーションの主な源はSchemeでした。関数型言語が何であるかはよくわかりませんが、面白い点は、関数を新しいコンテキストで渡したり適用したりするときに、クラスベースの継承が完全に不要になるのではなく、どういうわけか重要だと思われることです。
エリックReppen

2
-1も同様です。これはクロージャを説明するのではなく、スコープを説明します。
イズカタ

12

おそらく、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());

メソッドgetValueincreaseは、実際にはクロージャーであり、変数をカプセル化しますvalue


3
-1「クロージャに依存する」それは非常に主観的です。ありません。
レイノス

Raynos:クロージャーなしでプライベートメンバーを作成および使用する方法を教えてください。
user281377

1
@ammoQにはJavaScriptにはprivateというものはありません。あなたが意味したのは、「JavaScriptの古典的なオブジェクト指向エミュレーションはクロージャーに依存するから」です。JavaScript OOはプロトタイプであり、異なるパラダイムです。ただし、「従来のオブジェクト指向をエミュレートする必要があるため、JavaScriptでクロージャを使用しています」という質問に対する良い答えです。
Raynos

1
@keppla「オブジェクト指向はクロージャーに依存する」というのは主観的な意味です。オブジェクト指向のクロージャーはまったく必要ありません。
レイノス

2
あなたは私を売春婦として私を公開しています
...-user281377

4

JavaScriptを「耐えられる」ものにするライブラリの多くがそれらを使用しているためです。

見てくださいjQueryのプロトタイプMooToolsのが名前だけの人気3に、。これらの各ライブラリはeach、イテレータ関数を使用する好ましい反復方法として、コレクションのメソッドを提供します。その関数は、外部スコープの値にアクセスするときにクロージャーになります。

[1,2,3].each(function(item) {
   console.log(item);
});

Ajaxでのコールバック、Ext.jsでのイベント処理などはすべて関数を使用します。一度だけ呼び出される100種類の関数でコードを肥大化させたくない場合は、クロージャーが最適です。


1
なぜ閉鎖ではないのですか?console.logは外部スコープでconsole定義されているため、「自由変数」も同様です。そして、実際には、何も変わらないforループであり、悪い習慣なのはなぜですか?
ケプラ

@Raynos:私のクロージャの定義は「自由変数を含むブロック」であり、そのステータスを失うことはありません。自由変数はたまたまトップスコープにあります。しかし、私の主張を裏付けるために、このメソッドpastie.org/2144689を検討してください。なぜこれが悪いのでしょうか?
ケプラ

グローバルデータの「クローズ」は不正行為と見なされます。スコープチェーンを超えてデータにアクセスするのは問題ないことに同意します。そのアクセスを最小限に抑えるのは単に良い方法です。
レイノス

アクセスを最小化することに合意
ケプラ

配列反復子(forEach、map、reduceなど)では、それらがクロージャである理由はゼロであり、すべての状態が直接渡されることに注意してください。私はそれが閉鎖であるための反パターンと考えるだろう
レイノス

3

JavaScriptでの「良い」コーディングはクロージャーに大きく依存しているという他の回答にも同意します。ただし、それに加えて、おそらく各言語でこの機能がどのくらい使用されているかという問題にすぎません。JavaScriptには、最初の実装以来基本的にクロージャがあります。一方、C#には、Visual Studio 2008でリリースされた3.0以降のバージョンしかありません。

私が遭遇した多くのC#プログラマーは、まだ2.0プロジェクトに取り組んでいます。また、3.0または4.0で動作している場合でも、多くの場合2.0イディオムを使用しています。私は閉鎖が大好きです。概念がC#開発者の間で広まるにつれて、C#でより頻繁に使用されるようになります。


2

主な理由は、C#が静的に型指定されており、関数が単一の事前定義された環境にしかアクセスできないため、クロージャーの有用性が妨げられているためです。

一方、JavaScriptでは、クロージャーを使用すると、オブジェクトプロパティとしてアクセスし、ファーストクラスオブジェクトである場合、関数をメソッドとして動作させることができます。また、関数を異なる環境に挿入して、サブルーチンを異なるコンテキストで動作させることもできます。


1
静的型付けはこれと何の関係がありますか?クロージャーは直交しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.