首先,有關(guān)【遞歸】的知識(shí)請(qǐng)參考上一節(jié),鏈接地址:
根據(jù)JS中【椓】的知識(shí),我們知道js的基本數(shù)據(jù)類(lèi)型是值引用蕊蝗,引用類(lèi)型是地址引用盯捌。在淺拷貝中引用的地址同一個(gè)地址引用,修改其中一個(gè)對(duì)象的屬性值署隘,另一個(gè)對(duì)象也會(huì)產(chǎn)生影響宠能;而在深拷貝中,會(huì)開(kāi)辟一個(gè)新的內(nèi)存地址用來(lái)存放新對(duì)象的值磁餐,兩個(gè)對(duì)象對(duì)應(yīng)引用的內(nèi)存地址不一樣 违崇,修改一個(gè)對(duì)象并不會(huì)對(duì)另外一個(gè)對(duì)象產(chǎn)生影響。更詳細(xì)的描述請(qǐng)參考關(guān)于【椪锱】的介紹羞延。
【棧】:JS版數(shù)據(jù)結(jié)構(gòu)-棧
一脾还、淺拷貝
01. 概念
一個(gè)新的對(duì)象直接拷貝已存在的對(duì)象的對(duì)象屬性的引用伴箩,即淺拷貝。
02. 淺拷貝的實(shí)現(xiàn)方式
- 通過(guò)for循環(huán)復(fù)制給另一個(gè)對(duì)象
var obj = {
name: 'zhansan',
msg:{
txt: '123'
}
};
var o = {};
for (var k in obj) {
o[k] = obj[k];
}
console.log(o); //{name: "zhansan", msg: {txt: 123}}
- 通過(guò)Object.assign()
var o = {}
Object.assign(o, obj);
console.log(o);// {name: "zhansan", msg: {txt: 123}}
對(duì)于以上兩個(gè)拷貝鄙漏,obj中的name是基本數(shù)據(jù)類(lèi)型嗤谚,淺拷貝可以直接賦值得到棺蛛,msg是個(gè)對(duì)象,是復(fù)雜數(shù)據(jù)類(lèi)型呵恢,對(duì)象會(huì)開(kāi)辟一個(gè)新的內(nèi)存空間存儲(chǔ)msg對(duì)象鞠值,淺拷貝的時(shí)候時(shí)拷貝的地址是同一個(gè)地址。此時(shí)改變obj中的txt中的值渗钉,o中的txt的值也會(huì)改變彤恶。
obj.msg.txt = '456'
console.log(obj.msg.txt) // 456
console.log(o.msg.txt) // 456
- Array.prototype.slice.call()
var arr= [1, { x: 'zhao' }];
var arrNew = Array.prototype.slice.call(arr);
arrNew[1].x = 'zhang';
console.log(arrNew); // [ 1,{ x: 2 } ];
console.log(arr); // [ 1,{ x: 2 } ];
對(duì)于數(shù)組的拷貝,可以利用數(shù)組原型上內(nèi)置的slice方法鳄橘。
- arr.concat()
let arr1 = [1, { a: 2 }];
let arr2 = [3, { b: 4 }];
let arr3 = arr1.concat(arr2);
arr1[1].a = 222;
console.log(arr1);// [ 1, { a: 222 } ]
console.log(arr2);// [ 3, { b: 4 } ]
console.log(arr3);// [ 1,{ a: 222 }, 3,{ b: 4 } ]
數(shù)組合并也是一個(gè)淺拷貝声离。
二、深拷貝
01. 概念
深拷貝會(huì)另外拷貝一份一個(gè)一模一樣的對(duì)象,從堆內(nèi)存中開(kāi)辟一個(gè)新的區(qū)域存放新對(duì)象,新對(duì)象跟原對(duì)象不共享內(nèi)存瘫怜,修改新對(duì)象不會(huì)改到原對(duì)象术徊。
簡(jiǎn)單說(shuō):深拷貝把存放對(duì)象的空間地址,再?gòu)?fù)制一份給新對(duì)象鲸湃,這樣兩個(gè)對(duì)象直接互不干擾赠涮。
02. 深拷貝的實(shí)現(xiàn)方式
基于基本數(shù)據(jù)類(lèi)型直接循環(huán)復(fù)制,對(duì)于復(fù)雜數(shù)據(jù)類(lèi)型再次運(yùn)用for循環(huán)操作暗挑,每一級(jí)都要循環(huán)拷貝笋除。我們可以使用遞歸,對(duì)于遇到對(duì)象再次調(diào)用for循環(huán)即可炸裆。
function deepCopy(newobj, oldobj) {
for (var k in oldobj) {
var item = oldobj[k];
if (item instanceof Array) {
newobj[k] = [];
deepCopy(newobj[k], item)
} else if (item instanceof Object) {
newobj[k] = {};
deepCopy(newobj[k], item)
} else {
newobj[k] = item;
}
}
}
deepCopy(o, obj);
obj.msg.txt = 456
console.log(obj.msg.txt) //456
console.log(o.msg.txt) // 123
推薦閱讀: