JavaScript には、関数ステートメントと関数式があります。最初は名前付き関数を宣言し、後者は名前付き関数または無名関数に評価されます。関数式を使用しています。
あなたがやりたいと思うのは呼び出し式です。を返す関数をすぐに呼び出すだけですi
。
function f() {
var i, array = [];
for (i = 0; i < 3; i++) {
// The extra parentheses around the function are unnecessary here.
// But this is more idiomatic, as it shares syntax with how function
// expressions are introduced in statements.
// I.e. you could just copy-paste it anywhere.
array[i] = (function () {
return i;
})(); // don't rely on automatic semicolon insertion
}
return array;
}
3
また、問題のある例では、すべてのクロージャーが同じ変数をキャプチャするため、すべてのクロージャーが返されることに注意してくださいi
。
編集:前の段落をより明確にするために、本当に 3 つの異なるクロージャーが必要な場合は、それぞれに新しいスコープを作成する必要があります。他の言語とは異なり、Javascript はブロックを開くだけではスコープを作成しません。関数内にスコープを作成するだけです。これを行うには、次の 2 つの方法があります。
function f() {
var i, array = [];
for (i = 0; i < 3; i++) {
// With a parameter in an inner function
array[i] = (function (n) {
return function () {
// A new n is captured every time
return n;
};
})(i);
}
return array;
}
function f() {
var i, array = [];
for (i = 0; i < 3; i++) {
array[i] = (function () {
// With a variable in an inner function
var n = i;
return function () {
// A new n is captured every time
return n;
};
})();
}
return array;
}
ただし、次の例は間違っています。なぜなら、がブロックn
内で宣言されfor
ていても、関数の先頭で宣言され、ブロック内でのみ初期化されているかのようになるからfor
です。これは JavaScript であり、Java ではなく、C ではなく、C# ではなく、<括弧で囲まれた言語> でもないことを忘れないでください。
function f() {
var i, array = [];
for (i = 0; i < 3; i++) {
var n = i;
array[i] = function () {
return n;
};
}
return array;
}
同等のコード:
function f() {
var i, array = [];
var n;
for (i = 0; i < 3; i++) {
n = i;
array[i] = function () {
return n;
};
}
return array;
}