複製物件不含參考(deep-copy)
http://larry850806.github.io/2016/09/20/shallow-vs-deep-copy/
手動賦值(Shallow Copy)
把物件的參考賦予方式改用值的方式來傳遞,此時手動傳值的部分將會完全獨立。不過注意,在內層物件還是依據參考的方式傳遞。
for…in(Shallow Copy)
和手動賦值的方式接近,不過是使用for...in
的語法將原本的物件屬性,傳到新的物件上,這種方式同上也是屬於淺層賦值。
var string1 = "";
var object1 = {a: 1, b: 2, c: 3};
for (var property1 in object1) {
string1 = string1 + object1[property1];
}
console.log(string1);
// expected output: "123"
轉字串(屬於完全複製沒有深度限制。)
將物件轉換為一個不相干的字串,再將字串轉回物件,這種方式就會使兩個物件毫無關聯
使用套件
1.jQuery 套件中的 extend 可以複製物件,他也可以將加入參數使用深度複製 (deep copy)
let obj = {name: '王康寶', age:{child: 18}}
let copy = $.extend(true, {}, obj); //使用 jquery.extend
copy.name = '盧卡斯';
copy.age.child = 99; //更改 copy.age.child 的值
//輸出
console.log(obj); //{name: "王康寶", age:{child: 18}}
console.log(copy); //{name: "盧卡斯", age:{child: 99}}
2.lodash
lodash 也有提供_.cloneDeep用來做 Deep Copy
let obj = {name: '王康寶', age:{child: 18}}
let copy = _.cloneDeep(obj); //使用 lodash.cloneDeep
copy.name = '盧卡斯';
copy.age.child = 99; //更改 copy.age.child 的值
//輸出
console.log(obj); //{name: "王康寶", age:{child: 18}}
console.log(copy); //{name: "盧卡斯", age:{child: 99}}
ES6
Object.assign,Object.assign 能處理深度,只有一層的物件,沒辦法做到真正的 深拷貝(Deep Copy), 不過如果要複製的物件只有一層的話可以考慮使用他。
ES6 的 Set, Map 都沒辦法直接用 JSON 這種方法複製,還有 Class new 出來的實體 prototype 也會消失
到底要 deepClone 到多完整,還是要看需求
let obj = {name: '王康寶', age:{child: 18}}
let copy = Object.assign({}, obj);
//更改 copy.name 的值
copy.name = '盧卡斯';
//輸出
console.log(obj); //{name: "王康寶", age:{child: 18}}
console.log(copy); //{name: "盧卡斯", age:{child: 18}}
______________________________________________________________
https://kanboo.github.io/2018/01/27/JS-ShallowCopy-DeepCopy/
真的要完全複製一份還是乖乖遞迴到不是 Array / Object 慢慢複製會比較好
淺拷貝只複製指向某個物件的指標,而不複製物件本身,新舊物件還是共用同一塊記憶體
深拷貝會另外創造一個一模一樣的物件,新物件跟原物件不共用記憶體,修改新物件不會改到原物件。
一般物件
//////////////////
let a = {name:"abb"}
let b =a
undefined
b
{name: "abb"}
a
{name: "abb"}
a==b
true
a===b
true
b.name="troye"
"troye"
a
{name: "troye"}
////////////////////
let data = function(){
return {name:"alex"}
}
a= data()
{name: "alex"}
b=data()
{name: "alex"}
a==b
false
a===b
false
b.name="aaaaaa"
"aaaaaa"
a
{name: "alex"}
b
{name: "aaaaaa"}
物件複製有深度的問題,需要跑回圈,因此用fun幹掉