【JS】深拷貝與淺拷貝的區別,實現深拷貝的幾種方法

在項目中遇到了一個問題,js 中,爲了保存個對象數組不被改變,javascript

page.uploadMember = res.result.list;
page.nameArr = res.result.list;
//保存的page.uploadMember是爲了備份不被改動,
//代碼中有對page.nameArr進行操做

最後在取page.uploadMember的時候發現它也跟着改變了,做爲一個長期寫PHP,javascript研究不深刻的人百思不得其解,研究了很久都沒發現問題,最後請教了一下前端開發,發現JavaScript有深拷貝和淺拷貝的概念;前端

淺拷貝:假設B複製了A,當修改A時,看B是否會發生變化,若是B也跟着變了,說明這是淺拷貝,A、B是指向一個地址的;java

深拷貝:建立一個新的和原始字段的內容相同的字段,是兩個同樣大的數據段;兩個的地址是吧不同的;數組

這裏提到一點:函數

var a = [];
var b = [];
console.log(a == b); //false a和b地址不同,只是值敲剛好相等;

var c = a;
console.log(a == c); //true a和c地址同樣

c[0] = 1;
console.log(a); //[1] a隨着c改變而改變,這就是淺拷貝

  

JavaScript的基本數據類型:number,string,boolean,null,undefined五類。spa

引用數據類型 (Object類) 有常規名值對的無序對象{a:1},數組[1,2,3],以及函數等。code

基本類型--名值存儲在棧內存中對象

引用數據類型--名存在棧內存中,值存在於堆內存中,可是棧內存會提供一個引用的地址指向堆內存中的值blog

因此淺拷貝值存在於引用數據類型,c=a進行拷貝時,其實複製的是a的引用地址,而並不是堆裏面的值。遞歸

 

實現深拷貝的方法:

1封裝一個方法,遞歸拷貝對象各個層級的屬性:

 

複製代碼
function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判斷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,b);

 

 2.除了遞歸,咱們還能夠借用JSON對象的parse和stringify

function deepClone(obj){
    let _obj = JSON.stringify(obj),
        objClone = JSON.parse(_obj);
    return objClone
}    
let a=[0,1,[2,3],4],
    b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);

 

3.除了上面兩種方法以外,咱們還能夠借用JQ的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,b);
相關文章
相關標籤/搜索