やったこと
シャローコピーとディープコピーの挙動の理解がいまいちだったのでTypeScriptで試してみました。
ClassRoom型のmembersプロパティにUser型の配列が入っているような多次元のオブジェクトを以下の3パターンの方法でコピーした結果を比較しました。
・普通に代入
・locashのcloneDeepメソッドを利用
・スプレッド演算子を利用
・Object.assing
コード
// locashを読み込み
import * as lodash from 'lodash'
const _ = lodash
/**
* typeの定義
*/
type ClassRoom = {
name: string
members: User[]
}
type User = {
name: string
age: number
}
/**
* ClassRoom型とUser型のオブジェクトを定義
*/
let user1: User = {
name: 'Yorinton',
age: 18
}
let user2: User = {
name: 'ピーター・パン',
age: 15
}
let classroomA: ClassRoom = {
name: 'A',
members: [user1, user2]
}
/**
* 3パターンの方法で別変数にコピー
*/
// 普通に代入
let classroomB = classroomA
// lodashのcloneDeepを利用
let classroomC = _.cloneDeep(classroomA)
// スプレッド演算子
let classRoomD = { ...classroomA }
// Object.assign
let classRoomE = Object.assign(classroomA)
/**
* おおもとのオブジェクトの値を変更
*/
classroomA.name = 'B'
classroomA.members[1].name = 'ポーターピン'
/**
* 出力して結果を確認
*/
console.log(classroomA)
console.log(classroomB)
console.log(classroomC)
console.log(classRoomD)
console.log(classRoomE)
実行コマンド
$ npx ts-node ./src/copy.ts
※参照
https://qiita.com/Yorinton/items/28c46333e9d4f714e09c
結果
// classroomA (おおもとのオブジェクト)
{ name: 'B',
members: [ { name: 'Yorinton', age: 18 }, { name: 'ポーターピン', age: 15 } ] }
// classroomB (普通に代入) -> シャローコピーなので値が書き換わっている
{ name: 'B',
members: [ { name: 'Yorinton', age: 18 }, { name: 'ポーターピン', age: 15 } ] }
// classroomC (lodashのcloneDeep) -> ディープコピーなので値は書き換わっていない
{ name: 'A',
members: [ { name: 'Yorinton', age: 18 }, { name: 'ピーター・パン', age: 15 } ] }
// classroomD (スプレッド演算子) -> 1階層目のnameは書き換わっていない(ディープコピー)が、2階層目のnameは書き換わっている(シャローコピー)
{ name: 'A',
members: [ { name: 'Yorinton', age: 18 }, { name: 'ポーターピン', age: 15 } ] }
コピーの仕方で挙動が変わるので注意が必要。
※lodashインストール
lodashとTypeScript用に@types/lodashをinstall
$ npm install lodash
$ npm install @types/lodash