JavaScript Clone Object


JavaScript primitive and object

primitive type(原始/基本 型別)與non-primitive是JS裡主要兩種資料格式,對於non-primitive的物件來說,單純的指定只是將指標換個對象,實際上在記憶體中仍是指向該被複製的那份物件(by reference),想要deep clone(深層複製)一個物件有幾種方法:

1. 手動

var obj1 = { a: 1, b: 2 }
var obj2 = {}

for(i of obj1) {
    obj2[i] = obj1[i]
}

但這種方法如果遇到深層巢狀又加上陣列八成會哭

 

2. Object.assign

var obj1 = { a: 1, b: 2 }
var obj2 = Object.assign({}, obj1)

Object.assign是ES6的新招,這個做法很簡單,但是使用上有個條件:

目標物件必須只有一層(深層結構並不會一起跟著被複製一份)

也就是說:

// 包含一層以上的物件
var obj1 = { a: 1, b: [11, 12, 13] }
var obj2 = Object.assign({}, obj1)

// 更改其深層的東東
obj2.b.push(14)

obj1    // { a: 1, b: [ 11, 12, 13, 14 ] }
// 被污染了

 

 

3. 懶人法

var obj1 = { a: 1, b: [11, 12, 13] }
var obj2 = JSON.parse( JSON.stringify(obj1) )

// 試著改深層的東東
obj2.b.push(14)

obj1    // { a: 1, b: [ 11, 12, 13 ] }

透過轉成json字串再轉回來,達成深層複製,BUT

如果物件包含function就不會被複製過去(轉json會消失)

var myFun = function(){ console.log('function!') }
var obj1 = { a: 1, f: myFun }
var obj2 = JSON.parse( JSON.stringify(obj1) )

obj2    // { a: 1 }

因此這個方法僅適用於物件包含純資料時使用