什么是深淺復(fù)制
- 淺復(fù)制:淺復(fù)制就是復(fù)制一份引用,所有的引用對象都指向同一份數(shù)據(jù),并且都可以修改這份數(shù)據(jù).
- 深復(fù)制:所謂”深拷貝”,就是能夠?qū)崿F(xiàn)真正意義上的數(shù)組和對象的拷
var a = 5;
var b = a;
b = 1;
console.log(a);//5
console.log(b);//1
var a = {name:tom};
var b = a;
b.name = 'lisa';
console.log(a.name);//lisa
console.log(b.name);//lisa
由上述代碼可見,基本類型的賦值是深復(fù)制,引用類型的賦值是淺復(fù)制
如何實(shí)現(xiàn)引用類型深復(fù)制
淺復(fù)制是非常簡單的,那么對于引用類型來說要如何實(shí)現(xiàn)深復(fù)制呢
Object.assign()方法(一層深復(fù)制)
var obj = {name:'tom',age:10,like:{fruit:'apple'}};
var newObj = Object.assign({},obj);
console.log(newObj);
obj.name = 'lisa';
obj.like.fruit = 'peach';
console.log(newObj);
//第一個輸出結(jié)果
{
age: 10,
like: [object Object] {
fruit: "apple"
},
name: "tom"
}
//第二個輸出結(jié)果
{
age: 10,
like: [object Object] {
fruit: "peach"
},
name: "tom"
}
我們看到對象的第一層的屬性值的修改并不會互相影響,也就是說他們占用的是不同的內(nèi)存,但是第二層的屬性值的修改卻會互相影響,所以第二層復(fù)制過來得只是對象的引用,他們是指向同一塊內(nèi)存的
因此:Object.assign()方法只實(shí)現(xiàn)了對象第一層的深復(fù)制,更深層的都是淺復(fù)制.
-
JSON對象的json.stringify()方法和json.parse()方法-
json.stringify():將js對象轉(zhuǎn)換成字符串對象 -
json.parse():將字符串對象轉(zhuǎn)換成js對象
-
var obj = {name:'tom',age:10,like:{fruit:'apple'}};
var strObj = JSON.stringify(obj);
var jsObj = JSON.parse(strObj);
obj.name = 'lisa';
obj.like.fruit = 'peach';
console.log(jsObj);
//輸出結(jié)果
{
age: 10,
like: [object Object] {
fruit: "apple"
},
name: "tom"
}
我們看到在obj上的修改都不會影響到最終的jsObj,所以結(jié)合這兩個方法可以輕松實(shí)現(xiàn)對象的深復(fù)制.
-
原生js實(shí)現(xiàn)深拷貝
思路:如果對象屬性值是基本類型則直接賦值(前邊提過,基本類型的賦值屬于深拷貝)如果對象是引用類型,則遞歸至基本類型再賦值
function deepCopy(p,c) {
if(p === null || typeof p !== "object"){//非引用類型的深拷貝直接賦值
return p;
}
var c = c || {};
for (var i in p) {//引用類型,遍歷屬性
if (typeof p[i] === 'object') { //屬性值是引用類型
c[i] = (p[i].constructor === Array) ? [] : {};//屬性值是數(shù)組還是對象決定遞歸時傳入的c[i]是[]還是{}
deepCopy(p[i], c[i]);//遞歸拷貝
} else {
c[i] = p[i];//屬性值是基本類型,直接賦值
}
}
return c;
}
var target = {name:'tom',age:1,like:{fruit:['apple','peach']}};
var copyObj = (deepCopy(target));
console.log(copyObj);
target.name = 'lisa';
target.like.fruit = ['apple'];
console.log(copyObj);
//第一次輸出結(jié)果
{
age: 1,
like: [object Object] {
fruit: ["apple", "peach"]
},
name: "tom"
}
//第二次輸出結(jié)果
{
age: 1,
like: [object Object] {
fruit: ["apple", "peach"]
},
name: "tom"
}
我們可以看到上述代碼實(shí)現(xiàn)了對象的深拷貝,拷貝后兩個對象的修改并不會相互影響.