🍔
【JavaScript】Array.fill()で2次元配列を初期化するときに失敗した話
JavaScriptで配列を初期化するときにArray.fill()
をよく使っていたのですが、自分の理解不足で間違った使い方をしていたことがあったので、メモを残しておきます。
2次元配列の初期化
2次元配列が作りたくて以下のようにnew Array(3).fill([])
で初期化を行い、初めの要素に1
を追加しました。私としては[ [ 1 ], [], [] ]
と出力されてほしかったのですが、下記のような出力結果となりました。
const list = new Array(3).fill([]);
list[0].push(1);
console.log(list);
出力結果
[ [ 1 ], [ 1 ], [ 1 ] ]
全ての要素に同じものが追加されている(ように見えている)。
fillは引数がオブジェクトの場合、同じものを参照する
JavaScriptのリファレンスには以下のように書いてありました。
引数がオブジェクトの場合、同じオブジェクトを参照するみたいです。配列もオブジェクトと同じということでしょうか。
今回の場合はfill([])
で追加した2次元配列の各[]
は同じ参照先ということで、一つの[]
に追加したつもりでも、配列は同じものを参照しているので、すべてに1
が追加されたように見えているということだと思います。
一応以下のように確認したところtrueとなったため、そうだと思います。
const list = new Array(3).fill([]);
list[0].push(1);
console.log(list);
console.log(list[0]===list[1],list[1]===list[2]); // ←同じ参照先か確認
出力結果
[ [ 1 ], [ 1 ], [ 1 ] ]
true true
解決策
方法はいろいろあると思いますが、以下のように素直にループで回しました。
const list = new Array(3).fill([]);
for(let i = 0; i < 3; i++){
list[i] = [];
}
list[0].push(1);
console.log(list);
console.log(list[0]===list[1],list[1]===list[2]); // ←同じ参照先か確認
出力結果
[ [ 1 ], [], [] ]
false false
ちゃんと勉強しないといけませんね。
Discussion