JavaScriptで値を持つ配列を作成しようとして、以下のようなコードを書いたことはありませんか?

const arr = new Array(3).fill([]); 
arr[0].push(1);
console.log(arr); // [[1], [1], [1]]

予想に反して、すべての要素に同じ値が設定されてしまいました。これは配列の`fill()`メソッドの特徴によるものです。

問題の原因

`fill()`メソッドは、配列のすべての要素に対して同じオブジェクトへの参照を設定します。そのため、1つの要素を変更すると、すべての要素が同じように変更されてしまいます。

これは特にオブジェクトや配列を`fill()`で設定する際に注意が必要です。

解決方法

この問題を解決するには、以下のような方法があります:

1. Array.fromを使用する

const arr = Array.from({ length: 3 }, () => []);
arr[0].push(1);
console.log(arr); // [[1], [], []]

2. mapメソッドを使用する

const arr = new Array(3).fill().map(() => []);
arr[0].push(1);
console.log(arr); // [[1], [], []]

3. スプレッド構文を使用する

const arr = [...Array(3)].map(() => []);
arr[0].push(1);
console.log(arr); // [[1], [], []]

ベストプラクティス

配列の初期化時に各要素に独立したオブジェクトを設定したい場合は、`Array.from()`や`map()`を使用することをお勧めします。これらのメソッドは、各要素に対して新しいオブジェクトを生成するため、意図しない参照の共有を防ぐことができます。

// 推奨される書き方
const arr = Array.from({ length: 3 }, () => ({
  id: Math.random(),
  data: []
}));

このように書くことで、各要素が独立したオブジェクトとなり、予期せぬ動作を防ぐことができます。

まとめ

  • `fill()`メソッドは、オブジェクトや配列を設定する際に参照が共有される
  • `Array.from()`や`map()`を使用することで、独立した要素を持つ配列を作成できる
  • 初期化時には、要素の独立性を意識した実装を心がける

以上の点に注意して実装することで、配列の初期化に関する問題を回避することができます。