JavaScript:連番の配列を作る – あるいはJavaScriptの奇妙な仕様

JavaScript で連番の整数を要素に持つ配列を作る方法はいくつも考えられるだろうけど、こんなのを見つけた(見つけたコードそのままじゃなくて、少し整理してある)。

const initArray = (n) => [...Array(n)].map((_, i) => i);

いささかトリッキーだと思うけど、まっさきに思い浮かぶであろう for ループを使うよりも簡潔にかけている。もちろん、期待通りに動く。

> initArray(5);
[ 0, 1, 2, 3, 4 ]

自分のメモのために説明しておくと、Array(n) で要素 n 個の配列をつくり、スプレッド構文を使って別の配列リテラルの中に埋め込む。で、map メソッドを呼び出して、各要素をそのインデックス値に置き換える。結果的に 0 からはじまり n 個の連番をもつ配列が出来上がる。

さて、トリッキーだと思うのは、コンストラクタでつくった配列 Array(n) をわざわざスプレッド構文を使って別の配列リテラルに埋め込むところ [...Array(n)] だ。だけどこれがないと期待通りに動かない。

> Array(5).map((_, i) => i);
[ <5 empty items> ]

<5 empty items> ってなんだ。そりゃ初期化してないから空の配列なんだろうけど、長さ(要素数)は 5 なんでしょ?

> Array(5).length;
5

いままで使ったことがなかったので知らなかったけど、配列をコンストラクタ Array() でつくると、長さはあるけど何の値も入ってない、まさに空の配列が返ってくる。

> Array(5);
[ <5 empty items> ]

この「空(から)」は undefined でも null でもない。この配列にインデックスを使ってアクセスすると undefined が返ってくる。

> const a = Array(5);
undefined
> a[3];
undefined
> a[3] == undefined;
true

なら undefined が5個入った配列と等しいのかというとそれも違う。

> a == [undefined, undefined, undefined, undefined, undefined];
false

さらにいえば、リテラルでつくったから配列とも違う。

> a == [];
false

わけがわからないよ。