深拷貝和淺拷貝是針對引用類型的
淺拷貝:
簡單來說就是一個對象B復制另一個對象A,當改變B對象的值是A對象的值也隨之改變。
舉個例子
var obj1={a:1,b:5,c:3}; var obj2=obj1; obj2.b=2; console.log(obj1.b); //2 console.log(obj2.b); //2
可以看到兩個對象的值都被修改了。
淺拷貝:就是拷貝對象的引用,而不深層次的拷貝對象的值,多個對象指向堆內存中的同一對象,,任何一個修改都會是使得所有對象的值被修改,因為它們公用一條數據。
深拷貝:
簡單來說就是一個對象B復制另一個對象A,當改變B對象的值是A對象的值不會改變。
舉個例子:
var a=2; var b=a; b=3; console.log(a);//2 console.log(b);//3
以上例子說明兩個變量使用的是獨立的數據。對於基本數據類型來說不存在深拷貝、淺拷貝。直接賦值就是深拷貝。
深拷貝:深拷貝不會拷貝引用類型的引用,拷貝的是引用類型的值,形成一個新的引用類型。
如何實現深拷貝:
①JSON.Stringify(JSON.pare()) 不支持多層引用嵌套,不支持函數Map、Sep等類型的數據
var obj1={a:1,b:5,c:3}; var obj2=JSON.Stringify(JSON.parse(obj1)); obj2.b=2; console.log(obj1.b); //5 console.log(obj2.b); //2
②展開運算符 ...
var obj1={a:1,b:5,c:3}; var obj2=(...obj1) obj2.b=2; console.log(obj1.b); //5 console.log(obj2.b); //2
③Object.asssign(target,sourse)
var obj1={a:1,b:5,c:3}; var obj2=Object.assign({},obj1) obj2.b=2; console.log(obj1.b); //5 console.log(obj2.b); //2
④深拷貝函數,遞歸
// target 要拷貝的對象 function deepClone(target){ //定義一個拷貝對象 let result; // 判斷拷貝目標是不是Object對象 if(typeof target==='object'){ // 判斷是否是數組類型 if(Array.isArray(target)){ // 定義為數組 result=[]; for(let i in target){ result.push(deepClone(target[i])); } }else if(target===null){ // 直接賦值 result=null; }else if(target.constructor===RegExp){ // 直接賦值 result=target; // 不是特殊的對象 }else{ result={}; for(let i in target){ // 遞歸 result[i]=deepClone(target[i]); } } // 基本數據類型 直接賦值 }else{ result=target; } return result; }
var obj1={
a:{z:1,c:null},
b:[1,2,3,5],
c:function(){console.log(this.a)}
}
var obj2=deepClone(obj1);
console.log(obj2);
obj2.b[0]=2;
obj2.a[0]=2;
console.log(obj1.a)
console.log(obj2.a)
console.log(obj1.b)
console.log(obj2.b)
console.log(obj2.c())