50

次のコードを検討してください。

for (var i=0; i<100; i++) {
    // your code here
}
// some other code here
for (var i=0; i<500; i++) {
    // custom code here
}

適切なlintツール(jslint、jshint、または組み込みのIDE)は、警告を表示します- duplicate declaration of variable ikこれは、別の名前( 、 )の変数を使用するjか、宣言を先頭に移動することで解決できます。

var i; // iterator
for (i=0; i<100; i++) {}
for (i=0; i<500; i++) {}

私は両方のバリアントが好きではありません-私は通常上部に宣言をしません(そして私がそうしたとしても、ヘルパー変数を見たくありません-、、i)そして変数を変更するためにそれらの例で実際に悪いことは何も起こっていません'の名前。jk

私がこのようなことを書いた場合に備えて、私は巨大な警告が欲しいのですが:

for (var i=0; i<100; i++) {
    for (var i=0; i<500; i++) {} // now that's bad
}

そのような場合へのあなたのアプローチは何ですか?

4

4 に答える 4

50

JavaScriptには、他のコンピューター言語でよく知られている構造のように見える多くの構造があります。JavaScriptが他のほとんどのコンピューター言語とは別の方法で構造を解釈することは危険です。

JavaScriptを十分に知らない人(ちなみに一般的なケース)が次のような構造を見た場合

for (var i=0; i<100; i++) {
    // your code here
}

またはブロック内の変数の宣言を参照してください

{
    var i;
    //some code
    {
        var j;
        // some code
    }
}

そうすれば、ほとんどの読者は、ブロックレベルの変数が定義されると思うでしょう。JavaScriptにはブロックレベルの変数がありません。すべての変数は、定義された関数レベルとして解釈されます。

したがって、コードが5分間だけ記述されるテストコードだけではない場合、コード内で変数を定義することはありません。主な理由は、誤解される可能性のあるコードを記述したり、言語構造を使用したりしたくないということです

ちなみに、JSLintは、ブロック内の変数の定義が非常に悪いスタイルであるため、コード分析の処理を停止します。この動作を変更する可能性のあるJSLintオプションはありません。JSLintの動作は良くないと思いますが、ループ内の変数の宣言は、ほとんどの人がローカルループ変数forを持つコードとして読み取られるため、正しくないことに同意します。

使用する場合

for (var i=0; i<100; i++) {
    // your code here
}
// some other code here
for (var i=0; i<500; i++) {
    // custom code here
}

次に、JavaScriptは、関数の先頭にある変数のすべての宣言を移動します。したがって、コードは次のようになります

var i = undefined, i = undefined; // duplicate declaration which will be reduced
                                  // to one var i = undefined;

for (i=0; i<100; i++) {
    // your code here
}
// some other code here
for (i=0; i<500; i++) {
    // custom code here
}

したがって、コードの他のリーダーについて考えてください。間違った方法で解釈される可能性のある構造を使用しないでください。

于 2012-05-29T16:19:22.157 に答える
20

letキーワードはjavascript1.7で導入されました。ここでMDNドキュメントを見つけてください

内部に置き換えるvarと問題が解決し、ループのスコープ内でローカル変数を宣言できるようになります。ここでstackoverlowコミュニティの説明を確認してください:変数を宣言するために「let」と「var」を使用することの違いは何ですか?letfor loop

将来のコード:

for (let i = 0; i < someVar.length; i++) {
    // do your thing here
}
于 2015-04-28T02:49:56.937 に答える
8

ループが何をしているのかを示す名前の自己実行関数でループを囲むことをお勧めします。これにより、ループにブロックスコープが効果的に与えられます。例えば:

var users = response['users']
;(function appendUsers(){
    for (var i = 0; i < users.length; i++) {
        var user      = users[i]
        var userEmail = user['email']
        var userId    = user['id']
        /* etc */ 
    }
})() // appendUsers

これを行う場合:

var i
for (i = 0; i < someVar.length; i++) {
    for (i = 0; i < someOtherVar.length; i++) {
        // This is a bug that a validator will not notice.
    }
}

一方で:

for (var i = 0; i < someVar.length; i++) {
    for (var i = 0; i < someOtherVar.length; i++) {
        // This is a bug that a validator will warn you about.
    }
}
for (var i = 0; i < yetAnotherVar.length; i++) {
    // It will also warn you about this, but so what?
}

iイテレータとしての使用を停止できます。

for (var companyIndex = 0; companyIndex < companies.length; companyIndex++) {
    var company = companies[companyIndex]
}

とにかくjQueryを使用している場合は、そのjQuery.each()メソッドを使用できます。

$.each(someVar, function(i, value){
    // etc
})

ポリフィルコードArray.prototype.forEach()などを追加しない限り、IE8以前を動作させたい場合は使用できません。

于 2014-08-20T05:24:49.410 に答える
3

私は、map、filter、forEachなどの配列組み込み関数を使用する傾向があるため、この問題を完全に回避できます。これにより、スコープループ本体も自動的に提供されます。これも非常に便利です。

それらを使用することがユースケースと一致しない場合、私は通常、トップ宣言に頼ります。それは、あなたが言及した問題を回避できるようにするためです。

于 2012-05-29T15:09:42.793 に答える