1. ホーム
  2. javascript

[解決済み] ES6では、オブジェクトのプロパティを列挙する順序は明確に定義されていますか?

2023-05-10 23:16:48

質問

ES6では、オブジェクトのプロパティを列挙する順序は明確に定義されているのでしょうか?

var o = {
  '1': 1,
  'a': 2,
  'b': 3
}

Object.keys(o); // ["1", "a", "b"] - is this ordering guaranteed by ES6?

for(let k in o) {
  console.log(k);
} // 1 2 3 - is this ordering guaranteed by ES6?

どのように解決するのですか?

注意してください。 ES2020 では、以下のような古い操作でも for-inObject.keys はプロパティの順序に従わなければなりません。というのも、整数インデックスでないプロパティの順序は、プロパティがいつ作成されたかに依存するため、基本的なプログラムロジックにプロパティ順序を使用することは、おそらく良いアイデアではないという事実は変わりません。


ES2015-ES2019 の回答です。

について for-in , Object.keys そして JSON.stringify : いいえ。

他のいくつかの操作のために。 はい 、通常。

ES6 / ES2015 ではプロパティの順序が追加されましたが、そのためには for-in , Object.keys または JSON.stringify のように、レガシーとの互換性の問題から、この順序に従うようにします。

for-in ループは [[列挙]]する と定義されています(強調)。

の内部メソッド[[Enumerate]]が実行された場合、そのメソッドに対応する O の内部メソッドが呼び出されるとき、次の のステップが行われます。

Iteratorオブジェクトを返す( 25.1.1.2 ) のnextメソッドが反復処理する の列挙可能なプロパティの全てのString値のキーに対して反復処理を行います。 O . また イテレータオブジェクトは %IteratorPrototype% を継承していなければなりません ( 25.1.2 ). メカニックと オーダー を列挙することで、プロパティの は 指定されていない を指定することはできませんが、以下に示す規則に従わなければなりません。 [1] .

ES7 / ES2016では、[[Enumerate]]の内部メソッドが削除され、代わりに抽象的な操作である EnumerateObjectProperties を使用しますが、[[Enumerate]]と同様、順序を指定しません。

また、以下の引用もご覧ください。 Object.keys :

もし実装が for-inステートメントに特定の列挙順序を定義している場合、[...].

ということは の実装は、特定の列挙順序を定義する必要はありません。 . これは は確認されています。 は、ECMAScript 2015 言語仕様のプロジェクト エディターである Allen Wirfs-Brock が、仕様が完成した後に行った投稿で確認しました。

他の操作、たとえば Object.getOwnPropertyNames , Object.getOwnPropertySymbols , Object.defineProperties そして Reflect.ownKeys は、通常のオブジェクトの場合、以下の順序に従います。

  1. 整数のインデックス(該当する場合)、昇順で。
  2. その他の文字列キー (該当する場合)、プロパティの作成順序で。
  3. シンボル・キー (該当する場合)、プロパティ作成順。

この動作は [[OwnPropertyKeys]]です。 内部メソッドで定義されています。しかし、特定の エキゾチック・オブジェクト はその内部メソッドを少し違った形で定義します。例えば、Proxy の ownKeys トラップは任意の順序で配列を返すことができます。

console.log(Reflect.ownKeys(new Proxy({}, {
  ownKeys: () => ['3','1','2']
}))); // ['3','1','2'], the integer indices are not sorted!


[1] 下にはこう書いてあります。

[Enumerate]]は対象オブジェクトの自身のプロパティキーを取得する必要があります。 のように を取得する必要があります。

そして、[[OwnPropertyKeys]]の順番はきちんと決められているのです。しかし、それで混乱してはいけません。その "as if" は "the same properties" を意味するだけで、 "the same order" は意味しないのです。

これは、次のように見ることができます。 EnumerableOwnNames では、[[OwnPropertyKeys]]を使ってプロパティを取得し、それらを順番に並べています。

という Iterator が生成するのと同じ相対的な順序で並べます。 内部メソッド[[Enumerate]]が呼び出された場合に返されるIteratorが生成するのと同じ相対的な順序で、それらを並べ替えます。

もし[[Enumerate]]が[[OwnPropertyKeys]]と同じ順序で反復することを要求されるなら、順序を変更する必要はないでしょう。