1. 對於基本數據類型
其值在內存中占據着固定大小的空間,並被保存在棧內存中。當一個變量向另一個變量復制基本類型的值,會創建這個值的副本,並且我們不能給基本數據類型的值添加屬性。其為深拷貝。
2. 對於引用類型
淺拷貝:只復制指向某個對象的指針,而不復制對象本身,新舊對象共享一塊內存; 改變一個對象,另一個會隨之改變;
深拷貝:復制並創建一個一模一樣的對象,不共享內存,修改新對象,舊對象保持不變。
深拷貝:復制並創建一個一模一樣的對象,不共享內存,修改新對象,舊對象保持不變。
01 淺拷貝的實現
var arr = [1, 2, 3, '4']; var arr2 = arr; arr2[1] = "test"; console.log(arr); // [1, "test", 3, "4"] console.log(arr2); // [1, "test", 3, "4"]
我們可以看到,簡單的賦值便是淺拷貝,一個對象改變,另一個也隨之改變。
02 深拷貝的實現
1.使用JSON.stringfy();
var obj1 = { a: { b: 10 } }; var obj2 = JSON.parse(JSON.stringify(obj1)); obj2.a.b = 20; console.log(obj1); //{ a: { b: 10 } } console.log(obj2); //{ a: { b: 20 } } console.log(obj1 === obj2); // false console.log(obj1.a === obj2.a); // false
2.使用遞歸實現
function deepClone(obj){ let objClone = Array.isArray(obj)?[]:{}; if(obj && typeof obj==="object"){ for(key in obj){ //判斷ojb子元素是否為對象,如果是,遞歸復制 if(obj[key]&&typeof obj[key] ==="object"){ objClone[key] = deepClone(obj[key]); }else{ //如果不是,簡單復制 objClone[key] = obj[key]; } } } return objClone; } let a=[1,2,3,4], b=deepClone(a); a[0]=2; console.log(a);//[2, 2, 3, 4] console.log(b);// [1, 2, 3, 4]
當對象中有循環引用時:
即:
var a={c:1,d:2};
a.e=a;
設置一個標記,當目前對象已經被克隆過時,則不再循環調用
function deepClone(obj){ mark[obj]=1; let objClone = Array.isArray(obj)?[]:{}; for(key in obj){ //判斷ojb子元素是否為對象,如果是,遞歸復制 if(obj[key]&&typeof obj[key] ==="object"){ if(mark[obj[key]]==1){ objClone[key]=obj[key]; continue; } objClone[key] = deepClone(obj[key]); }else{ //如果不是,簡單復制 objClone[key] = obj[key]; } } return objClone; } var a={c:1,d:2}; a.e=a; mark={}; b=deepClone(a); console.log(a);//{c: 1, d: 2, e: {…}} console.log(b);//{c: 1, d: 2, e: {…}}
3.JQuery的extend()。
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷貝,true為深拷貝,false為淺拷貝;
target object類型 目標對象,其他對象的成員屬性將被附加到該對象上。
object1 objectN可選。 Object類型 第一個以及第N個被合並的對象。
let a=[0,1,[2,3],4], b=$.extend(true,[],a); a[0]=-1; a[2][0]=-1; console.log(a);//[-1,1,[-1,3],4] console.log(b);//[0,1,[2,3],4]
特別說明:concat(),slice()不是深拷貝,因為其只是一級屬性是深拷貝,二級屬性就不是了。
let a=[0,1,[2,3],4], b=a.slice(); a[0]=-1; a[2][0]=-1; console.log(a);//[-1,1,[-1,3],4] console.log(b);//[0,1,[-1,3],4]
let a=[0,1,[2,3],4], b=[].concat(a); a[0]=-1; a[2][0]=-1; console.log(a);//[-1,1,[-1,3],4] console.log(b);//[0,1,[-1,3],4]
