JavaScriptのクロージャを理解する
序章
この記事では、クロージャとは何か、JavaScriptがクロージャの恩恵を受ける理由の基本について説明します。
前提条件
この記事をフォローしたい場合は、次のものが必要になります。
- JavaScript変数、関数、スコープ、およびコールバックに精通していること。
クロージャーの定義
クロージャは、変数によって保持される永続的なスコープとして定義できます。 JavaScriptやRubyなどの言語はクロージャをサポートしています。これにより、プログラミングブロックが実行された後でも、変数が親スコープを参照できるようになります。これらの変数がどこかに参照を持っている限り、クロージャは存在します。
次のクロージャの例を考えてみましょう。
function outerFunction() { let delayed = veryLongOperation(); let innerFunction = function() { someCallback(delayed); } }
innerFunction
は、delayed
オブジェクトなどの親スコープ要素にアクセスできる関数です。
クロージャーの使用
クロージャーとは何かを見てきましたが、なぜそれらが役立つのでしょうか。
JavaScriptは、実行に関しては非同期にすることができます。 操作が完了すると、コールバックを使用する必要があります。 このコールバックは、呼び出し元/親と同じ実行コンテキストで実行する必要があります。 つまり、親が利用できる変数や関数はすべて、コールバックでも利用できるようにする必要があります。 これらのコールバックにクロージャがない場合は、必要なスコープメンバーを手動でバインドする必要があります。
クロージャーは、バックグラウンドでこれを処理することにより、私たちの生活をはるかに楽にします。 関数内に関数がある場合、内部関数はその存続期間を通じてスコープメンバーにアクセスできます。
次のクラス定義の例を考えてみましょう。
let classExample = function () { let randomNumber = Math.floor(Math.random() * 10); return function() { console.log(randomNumber); } }
内部関数のスコープチェーンは、classExample
関数のメンバーを含むように拡張されています。
クロージャーが作用するもう1つの例は、カリー化中です。 カリー化は、アリティを減らすために複数の関数を返すプロセスです。 これは、関数型プログラミングのパラダイムで使用され、状態の変化を減らします。
クロージャーをカリー化と一緒に使用して、JavaScriptクラスのプライベートメンバーを紹介できます。
function curryingExample() { let message = "Hello."; return { getMessage: function() { console.log('private message', message); } }; }
新しいcurryExample()
インスタンスを作成します。
let curry = new curryingExample();
message
へのアクセスを試みます:
console.log('undefined message', curry.message);
console.log(curry.message);
を実行すると、値はundefined
になります。
getMessage()
を使用してみてください:
curry.getMessage();
curry.getMessage();
を実行すると、値は"Hello."
になります。
結論
クロージャーはJavaScriptの非常に微妙でありながら強力な機能であり、クロージャーを理解することは、真剣なJavaScript開発者になるための非常に重要なステップです。