- 深拷貝:復(fù)制多層
- 淺拷貝:復(fù)制一層
在JavaScript使用過程中我們經(jīng)常會遇到這樣的場景;
var a = [1,2,3,4];
var b = a;
b[2] = 'other';
console.log(a); // [1,2,'ohher',4];
我們發(fā)現(xiàn),當(dāng)數(shù)組b的某一項(xiàng)發(fā)生變化時(shí),數(shù)組a對應(yīng)的項(xiàng)也發(fā)生了改變。
解析:當(dāng)我們把變量a的值賦給變量b的時(shí)候,變量b只是復(fù)制了a的指針
,在堆內(nèi)存中,變量a和變量b其實(shí)指向了同一個(gè)存儲區(qū)域。
那么怎么才能實(shí)現(xiàn)把a(bǔ)拷貝一份給b,當(dāng)b變化時(shí)a不受影響呢?
var arr = [1,["a","b"],3];
//var arr1 = arr.slice(0); // 與concat方法等效
var arr1 = arr.concat();
arr1[1][1] = "c";
arr1[3] = "4"
console.log(arr); //[1,["a","c"],3]
console.log(arr1); //[1,["a","b"],3,4]
通過上面的例子,我們發(fā)現(xiàn),給數(shù)組添加slice或concat方法,實(shí)現(xiàn)了一層拷貝,既一維數(shù)組的值實(shí)現(xiàn)了拷貝,二維數(shù)組還是受影響,也就是沒實(shí)現(xiàn)拷貝,這種情況通常稱為淺拷貝
那么又怎么實(shí)現(xiàn)深拷貝呢,我們這通過一個(gè)對象來演示?
var a = {
name : {age:100}
};
var str = JSON.stringify(a);
var b = JSON.parse(str);
b.name = {age:200};
console.log(a.name.age); //100 不受影響
當(dāng)b的age發(fā)生變化時(shí),a中的age并不會受影響,這樣我們就實(shí)現(xiàn)了深拷貝,這種方法也是現(xiàn)在比較流行的一種做法,但是IE下會有一些兼容性問題( IE低版本不認(rèn)識JSON.stringify() ),所以我們通過封裝函數(shù)的方法,重新實(shí)現(xiàn)一遍深拷貝和淺拷貝:
- 我們先建立一個(gè)對象
var obj = {
a:{
aa:10
},
b: 20
}
- 用for...in實(shí)現(xiàn)對象下面每個(gè)屬性的拷貝
// 淺拷貝
function shallowCopy(obj) {
var newObj = {}
for(var attr in obj){
newObj[attr] = obj[attr]
}
return newObj;
}
var obj2 = shallowCopy(obj);
obj2.b = 21;
obj2.a.aa = 11;
console.log(obj.b); //20 不受影響
console.log(obj.a.aa); //11 受影響
- 用遞歸實(shí)現(xiàn)對象下面所有屬性的拷貝
// 深拷貝
function deepCopy(obj){
if(typeof obj != 'object'){
return obj;
}
var newObj = {}
for(var attr in obj){
newObj[attr] = deepCopy(obj[attr]);
}
return newObj;
}
var obj2 = deepCopy(obj);
obj2.b = 21;
obj2.a.aa = 11;
console.log(obj.b); //20 不受影響
console.log(obj.a.aa); //10 不受影響
鑒于時(shí)間緊迫沒有仔細(xì)說明,以后有改動時(shí)在好好整理!