10

オブジェクトのプロパティを列挙すると、ループの開始時に現在のプロパティのスナップショットが取得され、スナップショットが繰り返されるように見えることに気付きました。以下は無限ループを作成しないため、私はこのように感じます。

var obj = {a:0,b:0}, i=0;
for (var k in obj) {
    obj[i++] = 0;
}
alert(i) // 2

デモhttp://jsfiddle.net/kqzLG/

上記のコードは、新しいプロパティを追加していることを示していますが、新しいプロパティは列挙されません。

ただし、削除演算子は私のスナップショット理論に反しているようです。これは同じコードですが、列挙される前にプロパティを削除します。

var obj = {a:0,b:0}, i=0;
for (var k in obj) {
    i++;
    delete obj.b;
}
alert(i) // 1

デモhttp://jsfiddle.net/Gs2vh/

上記のコードは、ループ本体が1回だけ実行されることを示しています。スナップショット理論が真である場合、2回実行されます。

何が起きてる?javascriptには、それが使用するある種の非表示のイテレータがあり、削除演算子はそれを何らかの形で認識していますか?

--反復順序について何かを想定していることに気付きました-具体的には、反復はプロパティの挿入時間に基づいて発生します。私はすべてのブラウザがそのような実装を使用していると信じています。

4

2 に答える 2

7

興味深い質問です。答えは仕様にあります(強調は私のものです):

プロパティを列挙するメカニズムと順序 (最初のアルゴリズムのステップ 6.a、2 番目のアルゴリズムのステップ 7.a)は指定されていません。列挙されているオブジェクトのプロパティは、列挙中に削除される場合があります。列挙中にまだ訪問されていないプロパティが削除された場合、そのプロパティは訪問されません。列挙中に列挙されているオブジェクトに新しいプロパティが追加された場合、新しく追加されたプロパティがアクティブな列挙でアクセスされるとは限りません。プロパティ名は、列挙内で複数回アクセスしてはなりません。

そのため、削除されたプロパティをそれ以上トラバースしてはならないことが明示的に指定されています。ただし、新しいプロパティを追加するための動作は実装に依存します。これは、プロパティを内部に格納する方法が定義されていないためです。

たとえば、Chrome では、数値プロパティがアルファベット順のプロパティよりも前に格納されているようです。

> Object.keys({a:0, 0:1});
  ["0", "a"]

ただし、アルファベット キーを追加しても、次のようになります。

var obj = {a:0,b:0};
for (var k in obj) {
    obj['c'] = 0;
    console.log(k);
}

cはトラバースされていないようで、出力はa bです。

キーは挿入順に保存されますが、Firefox も同じ動作を示します。

> Object.keys({a:0, 0:1});
  ["a", "0"]
于 2012-08-21T18:34:11.360 に答える
1

obj[i++] = 0;

最初の反復:

  • エントリ:i = 0、終了、i = 1

    2回目の反復:

  • 入口:i = 1、出口、i = 2

    さらに、javascriptfor inループは、オブジェクトを反復処理するときに順番に実行されることが保証されていません。したがって、delete obj.b;予測できない結果が生成されます。

  • 于 2012-08-21T18:33:12.897 に答える