js深拷貝與淺拷貝的區別及實現

1. 對於基本數據類型

其值在內存中佔據着固定大小的空間,並被保存在棧內存中。當一個變量向另外一個變量複製基本類型的值,會建立這個值的副本,而且咱們不能給基本數據類型的值添加屬性。其爲深拷貝。spa

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();code

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]

當對象中有循環引用時:blog

即:遞歸

var a={c:1,d:2};
a.e=a;內存

設置一個標記,當目前對象已經被克隆過期,則再也不循環調用get

 

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()。string

$.extend( [deep ], target, object1 [, objectN ] )io

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]
相關文章
相關標籤/搜索