プライベート変数のシミュレーション
プライベート変数が外部からアクセスできない理由
ループ内のクロージャ
参照エラーを避ける
クロージャはJavaScriptの非常に重要な機能です。それ現在のスコープは常に外側のスコープ内の変数にアクセスできます。 関数は独自のスコープを持つ JavaScript の唯一の構造であるため、クロージャの作成は関数に依存します。
プライベート変数をシミュレートする
function Counter(start) { var count = start; return { increment: function() { count++; }, get: function() { return count; } } } var foo = Counter(4); foo.increment(); foo.get(); // 5
ここで、Counter 関数は、関数 Increment と関数 Get の 2 つのクロージャを返します。 どちらの関数も外側のスコープ Counter への参照を維持するため、このスコープ内で定義された変数 count に常にアクセスできます。
プライベート変数に外部からアクセスできない理由
JavaScript ではスコープの参照や代入ができないため、外部から count 変数にアクセスする方法がありません。 唯一の方法は、これら 2 つのクロージャーを使用することです。
var foo = new Counter(4); foo.hack = function() { count = 1337; };
foo.hack はそのスコープで定義されていないため、上記のコードは Counter スコープで定義された count 変数の値を変更しません。グローバル変数 count を作成または上書きします。
ループ内のクロージャ
各ループでループ番号を呼び出す必要があると仮定して、ループ内でクロージャを使用するときによくある間違いが発生します
for(var i = 0; i < 10; i++) { setTimeout(function() { console.log(i); }, 1000); }
上記のコードは数値0から9を出力しませんが、数値10を出力します十回。
console.log が呼び出されると、匿名関数は外部変数 i への参照を保持します。この時点で for ループは終了し、i の値は 10 に変更されます。
望ましい結果を得るには、各ループで変数 i のコピーを作成する必要があります。
参照エラーを避ける
ループのシーケンス番号を正しく取得するには、匿名ラッパーを使用するのが最善です (翻訳者注: 実際、これは通常、自己実行匿名関数と呼ばれるものです)。
for(var i = 0; i < 10; i++) { (function(e) { setTimeout(function() { console.log(e); }, 1000); })(i); }
外部匿名関数はすぐに実行され、i をパラメーターとして受け取ります。このとき、関数内の e 変数には i のコピーが含まれます。
setTimeout に渡された匿名関数が実行されると、この関数は e への参照を持ち、この値はループによって変更されません。
同じ仕事を達成する別の方法があります。それは、匿名ラッパーから関数を返すことです。これは上記のコードと同じ効果があります。
for(var i = 0; i < 10; i++) { setTimeout((function(e) { return function() { console.log(e); } })(i), 1000) }
上記は JavaScript 上級シリーズ - クロージャとリファレンスの内容です。その他の関連コンテンツについては、PHP 中国語 Web サイト (m.sbmmt.com) に注目してください。