261

私は自分の JavaScript ファイルでJSLintを使用しました。エラーが発生しました:

for( ind in evtListeners ) {

行 41 文字 9 の問題: プロトタイプから不要なプロパティを除外するには、for の本体を if ステートメントでラップする必要があります。

これは何を意味するのでしょうか?

4

9 に答える 9

453

まず第一に、ループを使用して配列を列挙しないでください。for in一度もない。古き良きを使用してくださいfor(var i = 0; i<arr.length; i++)

この背後にある理由は次のとおりです。JavaScript の各オブジェクトには、 と呼ばれる特別なフィールドがありますprototype。そのフィールドに追加するものはすべて、そのタイプのすべてのオブジェクトでアクセスできるようになります。filter_0すべての配列に、ゼロを除外するクールな新しい関数を呼び出したいとします。

Array.prototype.filter_0 = function() {
    var res = [];
    for (var i = 0; i < this.length; i++) {
        if (this[i] != 0) {
            res.push(this[i]);
        }
    }
    return res;
};

console.log([0, 5, 0, 3, 0, 1, 0].filter_0());
//prints [5,3,1]

これは、オブジェクトを拡張して新しいメソッドを追加する標準的な方法です。多くのライブラリがこれを行っています。for inただし、現在どのように機能するかを見てみましょう。

var listeners = ["a", "b", "c"];
for (o in listeners) {
    console.log(o);
}
//prints:
//  0
//  1
//  2
//  filter_0

見える?突然、filter_0 が別の配列インデックスであると考えます。もちろん、実際には数値インデックスではありませんが、数値インデックスfor inだけでなく、オブジェクト フィールドを列挙します。そのため、すべての数値インデックスと を列挙していますfilter_0。ただしfilter_0、特定の配列オブジェクトのフィールドではありません。現在、すべての配列オブジェクトにこのプロパティがあります。

幸いなことに、すべてのオブジェクトにはhasOwnPropertyメソッドがあり、このフィールドが実際にオブジェクト自体に属しているか、それとも単にプロトタイプ チェーンから継承され、その型のすべてのオブジェクトに属しているかをチェックします。

for (o in listeners) {
    if (listeners.hasOwnProperty(o)) {
       console.log(o);
    }
}
 //prints:
 //  0
 //  1
 //  2

このコードは配列に対して期待どおりに機能しますが、配列に対してandを使用しないでください。は、配列のインデックスや値ではなく、オブジェクトのフィールドを列挙することに注意してください。for infor each infor in

var listeners = ["a", "b", "c"];
listeners.happy = "Happy debugging";

for (o in listeners) {
    if (listeners.hasOwnProperty(o)) {
       console.log(o);
    }
}

 //prints:
 //  0
 //  1
 //  2
 //  happy
于 2009-12-26T11:17:44.223 に答える
92

jslint の作者である Douglas Crockford は、この問題について何度も書いています (そして話しています)。彼のウェブサイトのこのページには、これをカバーするセクションがあります。

ステートメント用

for ステートメントのクラスは、次の形式にする必要があります。

for (initialization; condition; update) {
    statements
}

for (variable in object) {
    if (filter) {
        statements
    } 
}

最初の形式は、配列と事前に決定可能な反復回数のループで使用する必要があります。

2 番目の形式は、オブジェクトで使用する必要があります。オブジェクトのプロトタイプに追加されたメンバーが列挙に含まれることに注意してください。hasOwnProperty メソッドを使用して防御的にプログラミングし、オブジェクトの真のメンバーを区別することをお勧めします。

for (variable in object) {
    if (object.hasOwnProperty(variable)) {
        statements
    } 
}

Crockford は YUI シアターに関するビデオ シリーズも作成しており、そこで彼はこれについて語っています。Crockford の JavaScript に関する一連のビデオ/講演は、JavaScript に少しでも真剣に取り組んでいる場合は必見です。

于 2009-12-26T11:41:31.913 に答える
21

悪い: (jsHint はエラーをスローします)

for (var name in item) {
    console.log(item[name]);
}

良い:

for (var name in item) {
  if (item.hasOwnProperty(name)) {
    console.log(item[name]);
  }
}
于 2015-09-10T11:09:55.573 に答える
8

Vavaの答えは的を射ている。jQueryを使用する場合は、$.each()関数がこれを処理するため、より安全に使用できます。

$.each(evtListeners, function(index, elem) {
    // your code
});
于 2010-01-30T06:32:34.787 に答える
7

@all - JavaScript ではすべてがオブジェクト () であるため、「オブジェクトに対してのみ使用する」などのステートメントは少し誤解を招きます。さらに、JavaScript は厳密に型付けされていないため、1 == "1" が true になります (1 === "1" は true ではありませんが、Crockford はこれを重視しています)。JS における配列のプログラム的な概念に関して言えば、型付けは定義において重要です。

@Brenton - 用語の独裁者である必要はありません。「連想配列」、「辞書」、「ハッシュ」、「オブジェクト」、これらのプログラミング概念はすべて JS の 1 つの構造に適用されます。これは、名前 (キー、インデックス) 値のペアであり、値は他のオブジェクトにすることができます (文字列もオブジェクトです)。

だから、 new Array()と同じです[]

new Object()とほぼ同じです{}

var myarray = [];

すべてのインデックス (別名キー) は整数でなければならないという制限がある配列である構造を作成します。また、.push() を介して新しいインデックスを自動的に割り当てることもできます。

var myarray = ["one","two","three"];

実際に最善の対処法は次のとおりですfor(initialization;condition;update){

しかし、どうですか:

var myarray = [];
myarray[100] = "foo";
myarray.push("bar");

これを試して:

var myarray = [], i;
myarray[100] = "foo";
myarray.push("bar");
myarray[150] = "baz";
myarray.push("qux");
alert(myarray.length);
for(i in myarray){
    if(myarray.hasOwnProperty(i)){  
        alert(i+" : "+myarray[i]);
    }
}

配列の最適な使用法ではないかもしれませんが、物事が常に明確であるとは限らないことを示しています。

キーを知っていて、それらが整数でない場合は、配列のような構造オプションだけがオブジェクトです。

var i, myarray= {
   "first":"john",
   "last":"doe",
   100:"foo",
   150:"baz"
};
for(i in myarray){
    if(myarray.hasOwnProperty(i)){  
        alert(i+" : "+myarray[i]);
    }
}
于 2010-12-10T19:41:31.420 に答える
2

確かに言い方はちょっと極端だな

... for in ループを使用して配列を列挙しないでください。一度もない。古き良き for(var i = 0; i<arr.length; i++) を使用する

?

Douglas Crockford の抜粋のセクションを強調する価値があります。

...2 番目の形式はオブジェクトで使用する必要があります...

連想配列 (別名 hashtable / dictionary ) が必要な場合は、キーに数値インデックスではなく名前が付けられている場合、これをオブジェクトとして実装する必要がありますvar myAssocArray = {key1: "value1", key2: "value2"...};

この場合myAssocArray.length、null になり (このオブジェクトには「長さ」プロパティがないため)、i < myAssocArray.lengthあまり効果がありません。利便性の向上に加えて、連想配列は多くの状況でパフォーマンス上の利点をもたらすと期待しています。配列キーは便利なプロパティ (つまり、配列メンバーの ID プロパティまたは名前) になる可能性があるためです。配列は、if ステートメントを繰り返し評価して、目的の配列エントリを見つけます。

とにかく、JSLint エラー メッセージの説明にも感謝します。無数の連想配列を操作するときに、「isOwnProperty」チェックを使用します。

于 2010-04-19T14:54:07.450 に答える
0

これは、 hasOwnProperty メソッドで evtListeners のプロパティをフィルタリングする必要があることを意味します。

于 2009-12-26T11:09:54.583 に答える
0

for in/for/$.each のトピックに追加するために、$.each と for in を使用するための jsperf テスト ケースを追加しました: http://jsperf.com/each-vs-for-in/2

ブラウザー/バージョンによって処理方法が異なりますが、パフォーマンスの点で最も安価なオプションは $.each と straight out for in のようです。

for in を使用して連想配列/オブジェクトを反復処理し、何を求めているかを知っていて、他のすべてを無視している場合は、jQuery を使用している場合は $.each を使用するか、単に for in (そして休憩;最後の要素であるべきだとわかっているものに達しました)

配列を反復処理してその中の各キー ペアで何かを実行する場合、jQuery を使用しない場合は hasOwnProperty メソッドを使用し、jQuery を使用する場合は $.each を使用する必要があります。

for(i=0;i<o.length;i++)ただし、連想配列が必要ない場合は常に使用してください... lol chromeは、for inまたはよりも97%高速に実行されました$.each

于 2011-05-20T05:40:24.390 に答える