淺拷貝和深拷貝的'深淺'主要針對的是對象的‘深度’,常見的對象都是'淺'的,也就是對象里的屬性就是單個的屬性,而'深'的對象是指一個對象的屬性是另一個對象,也就是對象里面嵌套對象,就像嵌套函數一樣。
為什么要使用深拷貝和淺拷貝呢?
如果現有var obj1 = {...}
這個對象,想要復制對象obj1
,一貫的做法就是obj2 = obj1
,這時雖然obj2
擁有了obj1
的所有屬性,但obj2
卻不是自由的,因為它的改動會影響到obj1
,obj1
的改動也會影響到obj2
,這不是我們所希望的,所以要用到深拷貝和淺拷貝。
深拷貝和淺拷貝就是為解決對象的直接賦值后依然'連接'的問題,也就是共用一個引用,一個改變會影響到另一個。下面是常見的淺拷貝:
var obj = {
a:10,
b:20
};
function copy(obj) {
var newobj={};
for(arr in obj){
newobj[arr]=obj[arr]
}
return newobj;
}
obj2 = copy(obj); //成功復制出obj
console.log(obj2); Object {a: 10, b: 20}
obj2.a = 5; //更改了obj2的a
console.log(obj2.a); //5
console.log(obj.a); //10,obj2的改變不影響obj,說明拷貝后的對象和之前的對象不存在共用一個引用
Paste_Image.png
淺拷貝可以解決常見的現象,但倘若對象不是常見的那種呢?比如說對象里還有子對象,那么用淺拷貝就不夠徹底,比如如下代碼:
var obj = {
a: 10,
b: 20,
omg: {
name: 'xuguojun',
sex: 'male'
}
}
function copy(obj){
var newobj = {};
for(arr in obj){
newobj[arr] = obj[arr]
}
return newobj;
}
obj2 = copy(obj);
console.log(obj2); //成功復制出obj
obj2.omg.name = 'PDD'; //改變obj2.omg.name的值為'PDD'
console.log(obj2.omg.name);
console.log(obj.omg.name); //obj.omg.name的值也隨著改變
Paste_Image.png
上面代碼中,拷貝完成后更改了obj2.omg.name,結果obj.omg.name也隨之改變,說明omg依然存在共用同一個引用的現象,所以淺拷貝拷貝的并不徹底 。這時候深拷貝就該上場了,它能用遞歸的思想繼續深挖,直到最底層為止。
下面就是深拷貝了:
var obj = {
a: 10,
b: 20,
omg: {
name: 'xuguojun',
sex: 'male'
}
}
function deepcopy(obj){
var newobj = {};
for(arr in obj){
if (typeof obj[arr]==='object' && obj[arr] !== null) {
newobj[arr] = deepcopy(obj[arr]); //遞歸,核心代碼
} else {
newobj[arr] = obj[arr];
}
}
return newobj;
}
obj2 = deepcopy(obj);
console.log(obj2);
obj2.omg.name = 'PDD';
console.log(obj2.omg.name);
console.log(obj.omg.name);
Paste_Image.png
通過上述代碼可看出深拷貝拷貝的非常徹底,做到真正意義上的杜絕共用一個引用的問題。