私はこれの結果が10であることを知っています:
var es = [];
for (var i = 0; i < 10; i++) {
es[i] = function () {
console.log(i);
};
}
es[6]();
es[0] - es[9] の任意の数はまだ 10 ですが、なぜですか?
私はこれの結果が10であることを知っています:
var es = [];
for (var i = 0; i < 10; i++) {
es[i] = function () {
console.log(i);
};
}
es[6]();
es[0] - es[9] の任意の数はまだ 10 ですが、なぜですか?
ループの後i
は10
. 関数は の参照を出力しますi
。
作成されるのは整数オブジェクトのみです。これらconsole.log(i)
はすべてメモリ内の同じオブジェクトを参照しています。i
唯一の - の値はi
もちろん、ループの最後で 10 です。
行がクロージャーを作成することに注意してくださいconsole.log(i)
。これは、特に、によって参照される変数への新しい参照を作成していないことを意味しますi
。同じ参考書です。
この分析を行う良い方法は、コード内で新しい実変数が作成された回数を追跡し続けることです。C や C++ などでプログラミングしたことがあれば、整数が 4 バイトまたは 8 バイトのメモリを必要とすることをご存知でしょう。線for(var i = 0;
は、1 つのオブジェクトを作成するものと考えることができます。一つだけです。クロージャーはそれを行わないため、関数内では別のオブジェクトを作成するものは何もありません。
これは、 を実行するconsole.log(i)
までi
に、ループが終了して変更されたためです。
より正確には、ループは条件が false の場合、つまり is の場合に停止for
します。その後、10個の同一の関数があり、すべて同じ外部定義変数を使用しています。i < 10
i
10
i
この古典的な閉鎖のトリックを使用して修正できます。
var es = [];
for (var i = 0; i < 10; i++) {
(function(j){
es[j] = function () {
console.log(j);
};
})(i);
}
es[6]();
j
このコードが行うことは、スコープが無名関数呼び出しである新しい変数 を作成することです。i
これは、関数が呼び出されたとき (つまり、が呼び出されたときではなくループ中に)の値を保存する方法es[6]
です。
i
ループを参照しているため10
、つまり、console.log(i) を実行しているときです。i の値が 10 に変更されました。