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開発者になるための非常に重要なステップです。
これについては、KyleSimpsonののClosuresに関する優れた記事で詳しく説明されています。