LoginSignup
1
0

More than 5 years have passed since last update.

new Array(n) の初期化

Posted at

はじめに

const arr = new Array(10).map((value, index) => { ... });

のようなコードを書いていてうまくmapが回らなく困ったので、調べていたら以下の記事を見つけた。

new Array(len)と[undefined, ...]の違い - Qiita

なるほど、ここから察するにnew Array(len)はlengthは初期化するけれど、各要素は初期化されない、というよりは確保されていないような動作であることが分かりました。

new Array(2)[1]のように要素アクセスするとundefinedを返しますが、これは要素が返されているのではなく、プロパティがないのでundefinedというわけですね。

なるほど、undefinedが定義されているわけではないので、mapで関数が呼ばれていないらしい。
ECMAScript Language Specification - ECMA-262 Edition 5.1

ES2015+では

上記記事にあるようにfill()すれば問題なく、当初はそのやり方で対応していた。が、ES2015+なら以下の書き方でもいけるとの知見を得た。

const arr = [...Array(10)].map((value, index) => { ... });

[...Array(n)]は何をしている?

Spread Operatorで配列を展開している。
最初はmapと同じで要素が初期化されていないから展開もできないと思っていて、不思議だったので同様にECMAScriptの仕様を見てみる。

ECMAScript 2015 Language Specification – ECMA-262 6th Edition

ArgumentList : ... AssignmentExpression
 1. Let list be an empty List.
 2. Let spreadRef be the result of evaluating AssignmentExpression.
 3. Let spreadObj be GetValue(spreadRef).
 4. Let iterator be GetIterator(spreadObj).
 5. ReturnIfAbrupt(iterator).
 6. Repeat
  a. Let next be IteratorStep(iterator).
  b. ReturnIfAbrupt(next).
  c. If next is false, return list.
  d. Let nextArg be IteratorValue(next).
  e. ReturnIfAbrupt(nextArg).
  f. Append nextArg as the last element of list. 

ざっくり見ると Array.prototype.map と違ってhasOwnPropertyのチェックはしていないっぽい。
なので初期化がされていない要素はそのままundefinedとして返されており、結果undefinedでのfillと同様の動きをしているみたい。

仕様を読む大切さを知った。

1
0
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
1
0