0

今日は奇妙なバグが現れました。私たちのアプリでは、1つのファイルで、すべてのオブジェクトに、プロトタイプのように関数がアタッチされました。配列のプロトタイピングは行っていませんが、配列とオブジェクトにプロトタイプがあり、for(this in that)ループを実行すると、プロトタイプがアイテムとして含まれるため、それらをフィルタリングする必要がありました。したがって、2つの部分からなる質問:

  1. アレイのプロトタイプを作成すると、インデックスは+プロトタイプの数だけ増加しますか?したがって、array(a、b、c)にarray.prototype.function()がある場合、インデックスカウントは3または4になりますか?

  2. これが起こっているべきですか?

私たちが持っているjqueryプラグインの1つはすべて悪であると考えています。

4

3 に答える 3

2

array配列はオブジェクトであるため、多数のプロパティを持つことができますが、それ自体にカウントされるのは整数プロパティのみです。

var a = [];
alert(a.length); // 0
a.foo = "Ha";
alert(a.length); // 0
a[1] = 10;
alert(a.length); // 1

Array.prototype.shuffle = function() { ... }
alert(a.length); // 1

配列の処理に使用することはお勧めしませんがfor ... in、それでも使用する人もいます。 とfor ... inの両方が見つかります。fooshuffle

于 2012-09-06T17:28:08.570 に答える
2

「インデックスカウント」とは、あなたがlength財産を意味すると思います。その場合、最初の質問に対する答えは「いいえ」です。lengthプロパティは、配列の最高の数値インデックスに関連付けられています。したがって、たとえば、次のコードがある場合は、次のようにarr.lengthなります4

var arr = [];
arr[3] = true;
arr.length; //is 4

ただし、この状況では奇妙な動作をするfor-inループを参照しました。(上から) for-inを実行するとarr、次のようになります。

var output = "";
for (i in arr) { //Don't do this!
    output += i;
} 
output; //is "3" (not "0123" as you might expect)

前述したように、プロトタイプのプロパティは長さに影響を与えません。

Array.prototype.foo = true;
var arr = [];
arr[3] = true;
arr.length; //is 4

ただし、これらはfor-inループに影響を与えます(通常の状況では)。

var output = "";
for (i in arr) { //arr from the previous code block.
    output += i;
} 
output; //is "3foo" (or maybe "foo3", there's no guarantee form the spec either way)

これを回避する方法はいくつかあります。まず第一に、この種のナンセンスのために、配列オブジェクトでfor-inを使用することは絶対にしないでください。ただし、何らかの理由でそれを実行する必要がある場合は、次のように、常にhasOwnProperty()フィルターを使用してfor-inループを保護する必要があります。

var output = "";
for (i in arr) { //arr from the previous code block
    if (arr.hasOwnProperty(i)) {
        output += i;
    }
} 
output; //is "3"

繰り返しになりますが、for-inでの注文の保証はありません。したがって、もしそうなら、あなたはとして得るかもしれませんarr(それはありそうもないですが)。[1,1,1]output"201"

もう1つのオプションは、ES5の機能(存在する場合)を使用して、プロトタイプ化されたプロパティを列挙不可に設定することでオブジェクトレベルで保護することにより、他の人の悪いコーディングから身を守ることです。あなたはこのようにそれをするでしょう:

var foo = (function() { /* do something */ });
if(typeof Object.defineProperty === "function") { //If ES5
    Object.defineProperty(Array.prototype, "foo", {
        value: foo,
        enumerable: false //make it not enumerable
    });
} else { //For older browsers
    Array.prototype.foo = foo;
}

var arr = [], output = "";
arr[3] = true;

for(i in arr) { //Seriously, don't do this.
    output += i;
}
output; //is "3"

アレイに対してfor-inを実行することは悪い考えであることを十分に強調することはできません。実際、私はほとんどすべての状況下でfor-inを避ける傾向があります。なぜなら、そこにいる誰かがジャークになりたいかどうかわからず、これをコードの途中に投げ込むからです。

Object.prototype.ponies = "Ponies!";
于 2012-09-06T17:47:59.287 に答える
1

for (var i in array)を使用して配列を反復することを避け、0からまでの数値インデックスによってのみ配列を反復するarray.length - 1場合、誰かが配列プロトタイプに何かを追加しても問題は発生しません。for/inこれが、配列を反復する手法の使用を避ける必要がある理由です。

配列または配列プロトタイプに追加されたプロパティまたはメソッドの数に関係なく、配列を反復する安全な方法は次のとおりです。

for (var i = 0, len = array.length; i < len; i++) {
    // access array[i] here
}

var i = 0, len = array.length;
while (i < len) {
    // access array[i] here
    i++;
}
于 2012-09-06T17:32:34.283 に答える