🔥

JavaScriptの Shallow Copy と DeepCopy

2022/06/19に公開

実務において JavaScriptの Shallow Copy と DeepCopy の理解が足りず詰まってしまったことがあったので復習のためまとめます。

Shallow Copy(浅いコピー)

Shallow Copy
JavaScript で普通にコピーするとメモリが共有されているため、「コピーした側」と「コピーされた側」片方の値を変更するともう片方もつられて値が変更されてしまいます。

const dog = {
    name: "pochi",
    age: 8,
    favorite_food: "dog food"
}

console.log(dog)
//{ name: 'pochi', age: 8, favorite_food: 'dog food' }

const dog_shallowCopy = dog

console.log(dog_shallowCopy)
// { name: 'pochi', age: 8, favorite_food: 'dog food' }


// 浅いコピーでは dog_shallowCopy の name も tarou になる
dog.name = "tarou"

console.log(dog)
// { name: 'tarou', age: 8, favorite_food: 'dog food' }

console.log(dog_shallowCopy)
// { name: 'tarou', age: 8, favorite_food: 'dog food' }

Deep Copy(深いコピー)

Deep Copy はメモリを新たに消費して別の値として Copy することができます。
Deep Copy でよく使われる手法として JSON.parseJSON.stringify を組み合わせることで実現できます。MDNでもこの手法が紹介されています。

const dog = {
    name: "pochi",
    age: 8,
    favorite_food: "dog food"
}

console.log(dog)
//{ name: 'pochi', age: 8, favorite_food: 'dog food' }

const dog_deepCopy = JSON.parse(JSON.stringify(dog));

console.log(dog_deepCopy)
// { name: 'pochi', age: 8, favorite_food: 'dog food' }


// 深いコピーでは dog_deepCopy の name は pochi のまま 
dog.name = "tarou"

console.log(dog)
// { name: 'tarou', age: 8, favorite_food: 'dog food' }

console.log(dog_deepCopy)
// { name: 'pochi', age: 8, favorite_food: 'dog food' }

JSON.stringify と JSON.parse は何やってるのか

JSON.stringify はオブジェクトをJSON文字列にする機能があります。フロントからAPIに値を送信する時によく使われます。

console.log(JSON.stringify(dog))
// {"name":"pochi","age":8,"favorite_food":"dog food"}

JSON.parse は逆にJSON文字列をJavaScriptのオブジェクトに変換する機能になります。

const dog_json = JSON.stringify(dog)
// {"name":"pochi","age":8,"favorite_food":"dog food"}

console.log(JSON.parse(dog_json))
// { name: 'pochi', age: 8, favorite_food: 'dog food' }

まとめると、JSON.stringify でJSON文字列を新たに生成して(メモリを消費して)、そのJSON文字列を JSON.parse でオブジェクトに変換することでメモリを共有していないコピーされたオブジェクトが生成されていることとなります。

Discussion