new Array(n)に対しmap()メソッドが期待通りの動きをしなかった話
n回分のループ処理を行い、新しい配列を作りたいとします。 このような処理を行いたい場合、まず1つは普通にforループで行う方法が一般的かと思います。
const n = 3
const arr = []
for (let i = 0; i < n; i++) {
arr.push(i)
}
console.log(arr)
// > [0, 1, 2]
しかしforループを使ってはいけない呪いにかかってしまった方は、map、filter、reduceなどの配列メソッドを駆使しスマートに実装されるかと思います。 上記の処理をmapで再現する場合は、Array(n)で要素がn個分の空配列を作成し、その配列に対しmapを使うという方法が思いつくかと思います。 が、残念ながらこの方法はうまく動作しません。
const n = 3
const arr = Array(n).map((_, i) => i)
console.log(arr)
// > [empty × 3]
なぜなら、Arrayコンストラクターに任意の整数を1つ渡して作成した空配列は、lengthプロパティのみ設定され、インデックスキーは設定されない為です。
const emptyArray = Array(3)
console.log(emptyArray[0])
// > undefined ... [0]にundefinedが設定されている訳ではない
console.log(emptyArray.length)
// > 3
map、filter、reduceなどのメソッドは配列オブジェクトのインデックスを参照し処理を行います。 Array(n)で生成した配列にはインデックスキーが設定されていない為、期待通りの結果にはならなかったという訳です。
対処方法としてはいくつかあり、1つはスプレット演算子を使い新たな配列として展開する方法、もう1つはfill()メソッドを使い値を置き換える方法です。
const n = 3
const arr1 = [...Array(n)].map((_, i) => i)
console.log(arr1)
// > [0, 1, 2]
const arr2 = Array(n).fill().map((_, i) => i)
console.log(arr2)
// > [0, 1, 2]
期待通りの結果となりました!
いつも何気なく配列を扱っていますが、”JavaScriptは大部分がオブジェクト”というのが体感できる現象でした。 性質を理解し正しく扱えるようJavaScriptの理解を深めていきたいと思います。
Search Posts