8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript2Advent Calendar 2018

Day 20

JavaScriptのプロパティ列挙の3原則

Last updated at Posted at 2018-12-19

JavaScriptには、いくつもプロパティ列挙の方法があります。ただ、原則と歴史的な経緯を踏まえれば、どれが何を返すかは比較的わかりやすく整理できます。

TL; DR(今北産業)

  • プロトタイプをたどるのは演算子だけ
  • ownの付くメソッドはenumerableを見ない
  • enumerableを見るものはSymbolを通さない

ただし、Reflectにあるメソッドの中には一部例外も存在します。

Symbolの歴史的経緯

まずはそれぞれの手法が何を返すのかピックアップする前に、Symbolについて掘り下げておきます。

SymbolはES6から導入された、「プロパティのキーとして使える特殊な値」ですが、これはSymbol.iteratorのような特殊メソッドを、既存のJavaScriptの動作に影響しないように導入するために作られました。

そのため、ES5に存在したfor-inObject.keysなどではSymbolは扱わないようになっています(in演算子やhasOwnPropertyにシンボルを与えることはES5では不可能ですので、これらはシンボルで呼んでも正常動作しますが、互換性に影響はありません)。また、Symbolをキーにしたプロパティについて、enumerableによって動作を変えるものもありません。

各手法について

for-in

for-inは、プロトタイプまでさかのぼってenumerableな文字列キーのプロパティをリストアップしていきます。

Object.keysObject.valuesObject.entries

Object.keysでは、自分自身にあるenumerableな文字列キーのプロパティを詰めた配列を返します。

Object.valuesObject.entriesはES6以降で入ったものですが、ピックアップするキーの基準はObject.keysと同じです。

Object.getOwnPropertyNames

Object.getOwnPropertyNamesでは、自分自身にある(enumerableでないものも含めた)文字列キーのプロパティを詰めた配列を返します。Symbolは入りません。

Object.getOwnPropertySymbols

Object.getOwnPropertySymbolsは名前の通り、自分自身にあるSymbolのキーの一覧を返します。enumerableは影響しません。

Reflect.ownKeys

Reflect.ownKeysObject.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target)) と同じ値、つまり自身にあるプロパティすべて(文字列のあとにSymbol)を返します。

その他

プロパティの順序は、どの手法をとっても表示されるものについては一貫していますが、どのような順序になるかは規定されていません。また、プロトタイプが存在するオブジェクトで、プロトタイプと違うenumerableを設定するとわけのわからないことになることもありますので、要注意です。

外部リンク

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?