web-dev-qa-db-ja.com

「for ... of」ループの繰り返しはJavaScriptの配列の順序に従いますか?

for...inを使用して配列を反復処理しても順序は保証されませんが、ES6では新しい構成for...ofが導入されます。

for...ofの実装の制限付きテストは、配列で順番に反復することを示していますが、このプロパティは保証されていますか?

28
Heptic

for...inを使用して配列を反復処理しても順序は保証されませんが、ES6では新しい構成for...ofが導入されます。

for...ofの実装の制限付きテストは、配列で順番に反復することを示していますが、このプロパティは保証されていますか?

はい、配列のfor-ofの順序は array iterator definition によって保証されます:配列内のエントリを数値インデックス順に(存在しないものも含めて)訪問しますスパース配列のそれらthose—またはおそらくスパース配列のそれらnotであるべきです:-)):

ライブの例 on Babel のREPL、およびここに使用している人のためのオンサイトスニペット最新のブラウザ:

"use strict";
let a = [];
a[3] = 'd';
a[0] = 'a';
a.foo = "f";
for (let v of a) {
  console.log(v);
}

出力:

 a 
 undefined 
 undefined 
 d 

(2つのundefinedsはBabelのREPLで空白として表示されます。)

上記の2つの注意事項:

  1. 配列には列挙可能なプロパティfooがありますが、アクセスされません。

  2. 配列はまばらであり、for-ofdidは存在しない2つのエントリにアクセスします(インデックス1および2)。

for-inただし、ES = 2015(別名「ES6」)でさえ、notには保証された順序がありません。仕様を読むのは本当に簡単ですですが、そうではありません。詳細については この回答 をご覧ください。また、配列でfor-inを使用すると、配列の「インデックス」だけでなく、配列の列挙可能なプロパティ名のallにアクセスすることに注意してください。インデックス以外のプロパティ名を含む。たとえば、ES2015でも、これは次のとおりです。

"use strict";
var a = [];
a.foo = "f";
a[3] = 'd';
a[0] = 'a';
a.bar = "b";
var key;
for (key in a) {
  console.log(key);
}

...出力される可能性があります:

 0 
 3 
 foo 
 bar 

...または

 foo 
 bar 
 0 
 3 

...または他の何か。ただし、現在のJavaScript実装のセット(仕様では必須ではありません)では、他のプロパティの前または後に、すべて数字のキー(「インデックス」)がグループ化される可能性が非常に高いです。

Array.prototypeまたはObject.prototypeに列挙可能なプロパティがないことを前提としています(デフォルトではありません)。あれば、それらも見るでしょう。

配列のvaluesをループしたい場合、for-ofはES_2015の優れたツールであり、Array#forEachforEachは、スパース配列で特に便利です;存在しないエントリをスキップします)。 for-inはめったに良い選択ではありません。 this other answer にはオプションの包括的なリストがあります。

24
T.J. Crowder

_for...of_の実装の制限付きテストは、配列で順番に反復することを示していますが、このプロパティは保証されていますか?

はい。しかし、_for of_は配列を反復するだけではなく(_for in_がオブジェクトを列挙するように)、ハントダウンは少し複雑です。代わりに、すべてのiterableオブジェクトを、それぞれの反復子が提供する順序で一般的に反復します。

実際、配列はそのような反復可能要素であり、配列から反復子を取得する場合、配列内のすべての要素を配列内で見つかる順序と同じ順序で生成する反復子になります。 ArrayIteratorオブジェクトの仕様 を読むことができます。これらは基本的にfor (var index=0; index<array.length; index++) yield array[index];ループのように機能します。

5
Bergi

for..of のES6仕様に従って

for ( LeftHandSideExpression of AssignmentExpression ) Statement

LeftHandSideExpressionがObjectLiteralまたはArrayLiteralであり、LeftHandSideExpressionに一致する字句トークンシーケンスを、AssignmentPatternを目標シンボルとして使用してトークンを残さずに解析できる場合、次のルールは適用されません。代わりに、AssignmentPatternの早期エラールールが使用されます。

この文法ルールの定義に従って、for..ofループは、ArrayまたはObjectリテラル。

David Walshによる素敵なブログリンクがあります http://davidwalsh.name/es6-generators 彼はfor..ofループは反復子を使用して機能します。

2
Diptendu