🖨️

JavaScript ネストされた配列の深いコピー

2022/12/04に公開

結論

追記 JavaScriptのグローバルメソッドに追加された、structuredClone()を使う

const arr = [{ a: 100, b: { c: 2, d: 4 } }, 3, [4, 5, [6, [7, 8, 9]]], 'a']

const copy = structuredClone(arr) // [{ a: 100, b: { c: 2, d: 4 } }, 3, [4, 5, [6, [7, 8, 9]]], 'a']

失敗する例

const arr = [1, 2, 3]
const copy = arr
copy[0] = 4

// copyだけ変更したはずなのに、arrも変わってしまう
console.log(arr, copy) // [4, 2, 3], [4, 2, 3]

配列のコピーが、浅いコピーになっているので、コピーした配列の要素を変更すると、コピー元の配列も変更されてしまう

これに対処するには、深いコピーをしてコピー元との関係を切り離す必要がある

一次元配列の深いコピー

const arr = [1, 2, 3]

const copy1 = [...arr]
const copy2 = arr.concat()
const copy3 = Array.from(arr)
const copy4 = arr.slice()

上記の方法だと、ネストされた配列はディープコピーされないので、ネストされた配列には別の方法でコピーをする

ネストされた配列の深いコピー

structuredClone()を使おう

JavaScriptのグローバルメソッドに追加された、structuredClone()を使うことで簡単に深いコピーをすることが出来る

const arr = [{ a: 100, b: { c: 2, d: 4 } }, 3, [4, 5, [6, [7, 8, 9]]], 'a']

const copy = structuredClone(arr) // [{ a: 100, b: { c: 2, d: 4 } }, 3, [4, 5, [6, [7, 8, 9]]], 'a']

他の方法

mapを使う

二次元配列のみ対応
三次元配列や、配列以外のオブジェクトや値が入るとエラーが出てしまう

const arr = [
  [1, 2, 3],
  [4, 5, 6],
]

const copy = arr.map(v => v.map(v2 => v2))

JSON.parse, JSON.stringifyを使う

一次元配列、深いネスト、オブジェクト全てに対応。以前はこの方法が正解だった

const arr = [{ a: 100, b: { c: 2, d: 4 } }, 3, [4, 5, [6, [7, 8, 9]]], 'a']

const copy = JSON.parse(JSON.stringify(arr))

Discussion