◆ [1,,3] の 1 はキーがない状態
◆ 1 in [1,,3] は false
◆ forEach, for-in はキーがないところは実行されない
◆ for-of はキーがなくても実行される

先週くらいにこの話題を取り上げてるブログをいくつか見たのでなぜか流行ってたみたい?です
ちょっと遅れましたがここでも書いてみます

null でも undefined でもない状態

;[1,,3]
// [1, empty, 3]

Array(3)
// [empty × 3]

Chrome では empty と表示される状態があります
JavaScript では配列もオブジェクトです
配列の長さが 3 でもキーに 0,1,2 が常にあるとは限らず 1 のキーがないこともあります
数値のキーが存在しない場合はこうなります

length を指定してるだけでキーはなく 実体が存在しないのでこんな大きなサイズを確保してもすぐに結果が返ってきます
Array(1024 ** 3)
// [empty × 1073741824]

自分で length を指定したのと同じです

const arr = []
arr.length = 1024 ** 3
arr
// [empty × 1073741824]

大量の要素数で実際に中身があるものを作るとすごく時間がかかります
上の数だと Chrome ではクラッシュしました
Array(1024 ** 3).fill()
// CRASH!

キーがあるかを判定する

開発者ツール上では empty ですが実際に取得すると undefined です
const arr = [1,,3]
arr[1]
// undefined

empty であるかを判断するには in 演算子を使います
オブジェクトに指定のキーがあるかを判定するのと同じです

const arr = [1,,3]
0 in arr
// true
1 in arr
// false
2 in arr
// true

繰り返し処理

forEach や for-in ではキーがないところは実行されません

Array(3).forEach(value => console.log(value))
// no output

for(const key in Array(3)) console.log(key)
// no output

実行したい場合は for-of が使えます
for(const value of Array(3)) console.log(value)
// undefined
// undefined
// undefined

単純に N 回繰り返し処理をしたいみたいな場合にはこの方法が使えます
通常の for でループ変数 i を更新していく書き方よりは見やすくなります
わざわざ fill する必要もなく Array.from の map 機能を foreach 代わりに使うという意図がわかりづらくなることもしなくて済みます

for(const _ of Array(n)){
// write code here
}

通常の for 文でループ変数を 0 から 9 まで繰り返す処理は for-of でこう書けます
for(const i of Array(10).keys()){
console.log(i)
}

0,1,2,...

0 から順に数値を入れた配列を作る方法はいくつかあります

Array.from で empty のない配列に変換できます
第二引数にコールバック関数を指定すると 変換と同時に map 処理が行われます
Array.from(Array(3), (e, i) => i)
// [0, 1, 2]

fill で値を埋めて map することもできます
Array を 2 回書かなくていいのでちょっと短くなります
Array(3).fill().map((e, i) => i)
// [0, 1, 2]

Array.from の代わりに spread 演算子をつかって map するともうちょっと短くなります
;[...Array(3)].map((e, i) => i)
// [0, 1, 2]

0 から順の数字に限る方法ですが keys を使えばもっと短く出来ます
;[...Array(3).keys()]
// [0, 1, 2]