Help us understand the problem. What is going on with this article?

TypeScriptでオブジェクトのシャローコピーとディープコピーの挙動を確かめた

More than 1 year has passed since last update.

やったこと

シャローコピーとディープコピーの挙動の理解がいまいちだったので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
Yorinton
NetFlix、Hulu、U-next、T-verを経てAmazonプライムに流れ着く。3度の飯より好きなものは特に無いけど、3度の飯時には必ずと言っていいほどアニメを嗜む。PHP、JS、TS、Vue.js、Laravel、少しだけGo. 開発責任者.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away