最初に結論なんだけど、たぶん [...Array(length)].map(fn)
が良いかなと。
const arr = [...Array(3)].map((_, i) => i); console.log(arr); // => [ 0, 1, 2 ] console.log(arr.length); // => 3
...
で展開
配列オブジェクトは反復可能 (iterable) なので、スプレッド構文 ...
で展開してやることができます。
const arr = [...Array(3)]; console.log(arr); // => [ undefined, undefined, undefined ] console.log(arr.length); // => 3
短いし良さそう。
ただ記号の組み合わせになるので、初見でぎょっとするかも? すぐ慣れるとは思うけれど。
map()
と組み合わせて初期値
初期値も設定できます。初期値じゃないけど実質初期値。
const arr = [...Array(3)].map(() => 0); console.log(arr); // => [ 0, 0, 0 ]
オブジェクトを初期値にする場合は注意
オブジェクトを作る場合、丸括弧 ()
で括るのを忘れないように。 =>
に続けて波括弧 {}
を書くと違う意味になるので。
const arr = [...Array(3)].map((_, i) => { id: i + 1 }); console.log(arr); // => [ undefined, undefined, undefined ]
const arr = [...Array(3)].map((_, i) => ({ id: i + 1 })); console.log(arr); // => [ { id: 1 }, { id: 2 }, { id: 3 } ]
他のやり方も同じね。
new Array(length)
これが一番素直なやりかたではあるが、項目が空になってしまうという問題がある。
const arr = Array(3); console.log(arr); // => [ <3 empty items> ] arr.forEach((value) => { console.log(value); // ←一度も呼ばれない });
ここでいう空は undefined
が入っているわけではなく本当に空なので、 forEach()
や map()
が利きません。
というわけでだいたいの場合、こいつを起点にしてもうちょっとずつコードをこねこねしてやる必要があります。
new
はあってもなくても同じです。
const arr = new Array(3);
詳しくはこちら。
Array.from()
初見のわかりやすさならこちらか。
const arr = Array.from({ length: 3 }); console.log(arr); // => [ undefined, undefined, undefined ] console.log(arr.length); // => 3
可読性は悪くないが、ちょっと記述量が多いような?
初期値で埋める
第2引数へマップ関数与えられるので、 undefined
以外を設定したい場合に大変便利。
const arr = Array.from({ length: 3 }, () => 0); console.log(arr); // => [ 0, 0, 0 ]
fill()
map()
等は空の項目を飛ばすんだけど、 fill()
は飛ばさずに埋めてくれます。
const arr = Array(3).fill(0); console.log(arr); // => [ 0, 0, 0 ] console.log(arr.length); // => 3
undefined
以外にも任意の値で生成できるし、ハック的な不明瞭さもないし、良いんじゃないすかね。
ただし、オブジェクトを入れるのはだめです。
オブジェクトで埋めちゃだめ
各要素が同じオブジェクトのインスタンスを指してしまいます。
const arr = Array(3).fill({ a: 1 }); arr[0].a = 2; console.log(arr[0]); // => { a: 2 } console.log(arr[1]); // => { a: 2 } console.log(arr[0] === arr[1]); // => true
というわけで、やるならこう。
const arr = Array(3).fill().map(() => ({ a: 1 }));
結局長くなってしまった。 しかもメソッドを連鎖して呼び出すので、一行で書くには見た目がちょっと。
join()
からの split()
一度文字列に変換してから、配列へ再変換します。
const arr = Array(3).join(',').split(','); console.log(arr); // => [ '', '', '' ] console.log(arr.length); // => 3
要素は空文字列 ''
になります。
二段階あるのがハックっぽくて可読性低め。
apply()
関数オブジェクトのメソッド apply()
です。
const arr = Array.apply(null, Array(3)); console.log(arr.length); // => 3 console.log(arr); // => [ undefined, undefined, undefined ]
利点は古い環境でも使えるところ。
for
で頑張る
いやあこれはちょっと。
const arr = Array(3); for (let i = 0; i < arr.length; i++) { arr[i] = undefined; } console.log(arr); // => [ undefined, undefined, undefined ] console.log(arr.length); // => 3
おしまい
というわけで、 [...Array(3)].map(fn)
がよろしいかと存じます。
関連
- 配列のコンストラクターを改めて見てみる(配列とかおれおれAdvent Calendar2018 – 01日目)
- 配列風オブジェクトをArray.from()で本物の配列へ変換。(配列とかおれおれAdvent Calendar2018 – 05日目)
- 配列初期化子 [] のひみつ。(配列とかおれおれAdvent Calendar2018 – 09日目)