🎄

ENCA 8日目: プロパティ列挙順一律化

2024/12/08に公開

Reflect.ownKeys のプロパティ列挙順

ES2015 Reflect.ownKeys は対象オブジェクトが持つ [[OwnPropertyKeys]] 内部メソッドを呼び出します。Proxy や Module Namespace オブジェクトのような Exotic Object にはそれぞれ定義された [[OwnPropertyKeys]] 内部メソッドで順番が定義されますが、普通のオブジェクトは OrdinaryOwnPropertyKeys で定義された順に列挙されます。

OrdinaryOwnPropertyKeys は以下の順で列挙します。

  1. 配列のインデックスとなりうる整数(文字列)プロパティ(array index)をその数の順番で列挙する
  2. 1 以外の文字列プロパティを作成順に列挙する
  3. Symbol プロパティを作成順に列挙する
const obj = {
  [3]: 3,
  foo: "foo",
  [1]: 1,
  [Symbol("bar")]: "bar",
  "0": 0,
  baz: "baz",
};
console.log(Reflect.ownKeys(obj)); // ["0", "1", "3", "foo", "baz", Symbol(bar)]

プロパティ列挙順一律化

ES2020 for-in mechanics の提案により、今まで実装依存だった for...in の列挙順が定められました。

なお for...in はレガシー機能で、[[Prototype]] のもつ列挙可能なプロパティも対象となってしまうため使わない方が良いです。ESLint の guard-for-in ルールにより、Object.hasOwn によるプロパティ所有チェックをちゃんとしているか確かめることが可能ですが、通常 Object.keysObject.entries を使ったほうが良いと思います。

さて for...in の列挙順が定められたことに呼応して、Object.keys, Object.values, Object.entries, JSON.parse そして JSON.stringify の列挙順も Reflect.ownKeys と一律同じにしようという話になり、承認されました。

https://github.com/tc39/ecma262/pull/1793

Discussion