3

それで、今日JavaScriptをいじり始めました。そして、何かが関数であると確信しているように見え、同時にそれは関数ではないと確信しているという面白いケースに出くわしました。このコードは問題を示しています:

var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
    arr1[i] = function(n) { return n + i }
}

var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
    arr2[j] = function(n) { return arr1[j](n) }
}

typeof arr2[0] // "function"
arr2[0](2)     // TypeError: Property '1' of object [object Array] is not a function

ここから、に変数を割り当てることができarr2[0]、エラーが持続します。これを複製するためにクロージャまたは配列が必要かどうかはわかりません。

私のコードに何か問題がありますか、それともこれはJavaScriptの奇妙な点の1つにすぎませんか?これは特に答えが必要なことではありませんが、少しばかげているので、理由があるかどうか知りたいです。

4

4 に答える 4

3

これは実際にクロージャと少し関係があります。

まず、次のコードを使用します。

for (j = 0; j < arr2.length; j++) {
    arr2[j] = function(n) { return arr1[j](n) }
}

変数jは最初に値0を保持するarr2[0]ため、関数への参照に設定されます。

次に、jがインクリメントされ、値が1になります。これにより、ループが終了します。

さて、関数が呼び出されたとき

return arr1[j](n)

クロージャjが原因で、最終値は1のままです。これはその配列の無効なインデックスです。

もう1つ指摘しておきます。ループは新しいforクロージャーを作成しないため、無名関数がその反復内の値を囲むことを期待している場合、その仮定は間違っています。で宣言された関数全体jの中には、の単一のインスタンスがあります。jj

于 2013-03-26T04:14:56.493 に答える
1

ループ内のクロージャを利用しようとしていると思いますが、そのようには機能しません。

iの値を操作したい場合jは、ループの各ステップで、以下に示すように無名関数を利用する必要があります。

var arr1 = Array(1)
for (i = 0; i < arr1.length; i++) {
    arr1[i] = (function(i){
        return function(n) { 
            return n + i 
        };
    })(i);
}

var arr2 = Array(1)
for (j = 0; j < arr2.length; j++) {
    arr2[j] = (function(j){
        return function(n) { 
            return arr1[j](n)
        }
    })(j);
}

typeof arr2[0] 
arr2[0](2)

デモ:フィドル

于 2013-03-26T04:18:51.290 に答える
0

変なことは何もしていません。

関数ではないもの(の値、arr1[1]であるundefined)を試しているだけです。

于 2013-03-26T04:13:45.797 に答える
0

次の形式で配列を初期化する方がおそらく安全です。

var arr1 = [];

または、「配列」を使用している場合は、次のように初期化する必要があります。

var arr1 = new Array();
于 2013-03-26T04:14:52.733 に答える