7

変数は Javascript でスコープ化された関数であることを覚えています。しかし、ループ内でローカル変数を再定義した場合の動作はどうなりますか。一般的な使用例の 1 つは、ネストされたループです。以下のコードでは、j を i に変更すると、外側のスコープの i の値が内側の for ループと同じであるため、外側の for ループは 1 回の反復後に終了します。私はvarを使用しているので、(他の言語と同様に)内部のfoループ内で再定義されると予想していました。これはJSでは、関数スコープ内でローカル変数を再宣言して使用する方法がないということですか。

for (var i = 0, len = x.length; i < len; i++) {
            ...
            for (var j = 0, len = y.length; j < len; j++) {
                ...
            }
        }
4

3 に答える 3

8

おっしゃる通り、JavaScript には関数スコープしかありません。変数宣言は、宣言されているスコープの先頭に引き上げられます。あなたの例は次のように解釈されます:

var i, j, len; //Declarations are hoisted...
for (i = 0, len = x.length; i < len; i++) { //Assignments happen in place
    for (j = 0, len = y.length; j < len; j++) {

    }
}

この部分に関しては:

j を i に変更すると、外側の for ループは 1 回の反復後に終了します。

に置き換えるji、内側のループの最初の繰り返しの後、iになり、 と の差にy.length - 1応じて、外側のループが続行または停止します。x.lengthy.length

内部動作の実際の説明に興味がある場合は、ECMAScript 仕様 (Declaration Binding Instantiation)で詳しく説明されています。要約すると、コントロールが新しい実行コンテキストに入るたびに、次のことが起こります (これよりも多くのことが起こりますが、これはその一部です)。

コード内のVariableDeclarationおよびVariableDeclarationNoIn dごとに、ソース テキストの順に実行します。

  • dnをdの識別子とします
  • varAlreadyDeclaredを、引数としてdnを渡してenv のHasBinding具象メソッドを呼び出した結果とします。
  • varAlreadyDeclaredが false の場合 、
    • dnconfigurableBindingsを引数として渡して、 env のCreateMutableBinding 具象メソッドを呼び出します。
    • 引数としてdn、 undefined 、およびstrictを渡して、 env のSetMutableBinding 具象メソッドを呼び出します。

これは、実行コンテキストごとに変数を複数回宣言すると、事実上無視されることを意味します。

于 2012-09-25T12:57:29.847 に答える
4

すべてvarの宣言は現在のスコープの先頭に配置されるため、コードは次のようになります。

   var i, j, len;
   for (i = 0, len = x.length; i < len; i++) {
        ...
        for (j = 0, len = y.length; j < len; j++) {
            ...
        }
    }

これを確認してください: JavaScript のスコープと巻き上げ

于 2012-09-25T12:57:05.930 に答える
0

JS にはブロック レベルのスコープはありません。

ただし、コードで同じ変数名を使用/再宣言することがどうしても必要な場合は、次のことができます。

function loopIt(arr, fn, scope) {
    for (var i = 0, len = arr.length; i < len; i++) {
        fn.call(scope || this, arr[i], i, arr);
    }
}

そして、次のように使用します。

var firstArr = ["a", "b"];
var secondArr = ["c", "d"];

loopIt(firstArr, function(item, i) {
    var msg = "Hey it's '" + item + "'";
    console.log(msg);

    // if you want access to the parent scope's var
    var scopedItem = item;

    loopIt(secondArr, function(item, i) {
        var msg = "Hello it's '" + item + "' in '" scopedItem + "'";
        console.log(msg);
    });
});

これにより、次の結果が得られます。

Hey it's 'a'
Hello it's 'c' in 'a'
Hello it's 'd' in 'a'
Hey it's 'b'
Hello it's 'c' in 'b'
Hello it's 'd' in 'b'
于 2012-09-25T13:46:54.523 に答える