JavaScriptの「for-in」ループに「var」または「var」がありませんか?


99

for-inJavaScriptでループを記述する正しい方法は何ですか?ブラウザは、ここに示す2つの方法のいずれについても問題を発行しません。最初に、反復変数xが明示的に宣言されるこのアプローチがあります:

for (var x in set) {
    ...
}

そして代わりに、このアプローチはより自然に読みますが、私には正しくないようです:

for (x in set) {
    ...
}

バンドルファイル生成のWebPACKは、forループでエラーを引き起こしていた理由をトラブルシューティングするときだけは、この記事に出くわしたvarイテレータを宣言するために使用されませんでしたiUncaught ReferenceError: i is not defined。したがって、これから使用します:/ webpackは「グローバル」変数を奇妙に扱います。詳細については、次を参照してください: stackoverflow.com/a/40416826
user1063287

回答:


103

を使用するvarと、変数のスコープが縮小されます。それ以外の場合、変数はvarステートメントを検索する最も近いクロージャを検索します。が見つからない場合varはグローバルです(厳密モードの場合using strict、グローバル変数はエラーをスローします)。これにより、次のような問題が発生する可能性があります。

function f (){
    for (i=0; i<5; i++);
}
var i = 2;
f ();
alert (i); //i == 5. i should be 2

var iforループで書き込むと、警告が表示されます2

JavaScriptスコープとホイスト


4
質問に答えていない、これがないためでために、ループのための通常のためである。
IllidanS4は望んでモニカ戻って

forループにvarがないことよりも巻き上げが原因でi == 5になったのではないですか?
Snekse 2013

1
これに対するもう1つの重要な側面は、厳密モードではgobalプロパティの暗黙的な作成が禁止されるため、varステートメントなしで標準の「for in」ループを使用すると、実際には失敗し、ReferenceErrorが返されることです。
dkugappi 2013年

2
しかし、Javaの場合、var内部にforヘッドを配置すると、forループでローカルのように見えますが、そうではありません。したがって、以下のuser422039のスタイルを使用します。
njlarsson 2014年

2
1つのスコープに複数のforループがある場合はどうなりますか?インデックスを再利用する(varではない)か、何度も使用しない新しい変数(j、k、l、m、…)をたくさん宣言する必要があります。
armin

40

最初のバージョン:

for (var x in set) {
    ...
}

と呼ばれるローカル変数を宣言しますx。2番目のバージョン:

for (x in set) {
    ...
}

ではない。

場合x(あなたが持っている。すなわち、すでにローカル変数であるvar x;か、var x = ...;どこかそれ以前のあなたの現在のスコープ内(つまり、現在の関数))、その後、彼らは同等になります。がまだxローカル変数でない場合、2番目を使用すると、暗黙的にグローバル変数が宣言されますx。このコードを考えてみましょう:

var obj1 = {hey: 10, there: 15};
var obj2 = {heli: 99, copter: 10};
function loop1() {
    for (x in obj1) alert(x);
}
function loop2() {
    for (x in obj2) {
        loop1(); 
        alert(x);
    }
}
loop2();

アラートにこれを期待するかもしれないheythereheliheytherecopter、しかし、以来x、それは警告する1と同じですheytherethereheytherethere。あなたはそれを望まない!ループで使用var xしますfor

それをすべてオフに先頭に次の場合forループはグローバルスコープ(すなわちない機能で)であり、その後、ローカルスコープは(スコープはx、あなたが使用している場合に宣言されているvar x)は、グローバルスコープと同じである(スコープはx、暗黙的に宣言されていますxvarなしで使用する場合)、2つのバージョンは同じになります。


3
最後に、説明と素晴らしい例を含む完全な回答。そしてそれは本当に質問に答えます。
IllidanS4はモニカに

22

ローカル変数はvar常にで宣言する必要があります

それがあなたがしたいことであることが確実である場合を除いて、「for ... in」ループを使用すべきではありません。実際の配列を反復する(これはかなり一般的です)には、常に数値インデックスを持つループを使用する必要があります。

for (var i = 0; i < array.length; ++i) {
  var element = array[i];
  // ...
}

「for ... in」を使用してプレーン配列を反復処理すると、ループが数値でインデックス付けされたもの以外の配列の属性を取得する可能性があるため、予期しない結果が生じる可能性があります。

編集 —ここ2015年には.forEach()、配列を反復処理するために使用することもできます

array.forEach(function(arrayElement, index, array) {
  // first parameter is an element of the array
  // second parameter is the index of the element in the array
  // third parameter is the array itself
  ...
});

この.forEach()メソッドは、IE9以降のArrayプロトタイプに存在します。


12

実際、for見出し内の宣言が嫌いなら、次のようにすることができます。

var x;
for (x in set) {
    ...
}

この質問の他の回答で述べたように、まったく使用varしないと、グローバルプロパティの割り当てなどの不要な副作用が生じます。


9

でループ変数を宣言したものを使用してくださいvar。暗黙的に宣言された変数には、おそらく意図したものとは異なるスコープがあります。


9
for(var i = 0; ...)

よく見られるパターンですが、

for(int i; ...)

C ++では、変数のスコープはforブロックではありません。実際、はvar囲みスコープ(関数)の最上部に巻き上げられるため、ローカルiforループの前(現在のスコープ/関数の開始後)とその後の両方で効果的に利用できます。

つまり、次のようにします。

(function(){ //beginning of your current scope;
 //...
 for(var i in obj) { ... };
})();

と同じです:

(function(){ //beginning of your current scope;
 var i;
 //...
 for(i in obj) { ... };
})();

ES6には、スコープをforブロックに制限するlet(の代わりにvar)キーワードがあります。

もちろん、暗黙的なグローバルではなく、ローカル変数(varor letまたはorで宣言されたものconst(ES6の場合))を使用する必要があります。

for(i=0; ...)または、(必要にfor(i in ...)応じて)使用し、宣言されていない場合は失敗します。"use strict";i



4

varはパフォーマンス上の理由から良いと思います。

Javascriptはグローバルスコープ全体を調べて、xがすでにどこかに存在しているかどうかを確認しません。


3

一般的な観点から、最初のバージョンはループのスコープ内に存在する必要があるインデックス用であり、もう1つはループのコンストラクターが呼び出されたスコープ内の任意の変数です。

forループ内でループのインデックスを使用する場合、次の行で他の人がこれを必要としない場合は、変数を「var」で宣言して、「x」が0で初期化されるループのインデックスであることを確認してください。もう1つは、このコンテキストで他の「x」変数が使用可能な場合、ループのインデックスによって上書きされます(論理エラーが発生します)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.