1. 程式人生 > >Js中物件的深拷貝和淺拷貝

Js中物件的深拷貝和淺拷貝

淺拷貝:只拷貝物件的基礎屬性值,對屬性值為物件或陣列的屬性則拷貝指標。  深拷貝:拷貝物件的所有屬性作為一個全新的物件。拷貝前後的物件互不影響。

淺拷貝僅僅是指向被複制的記憶體地址,如果原地址中物件被改變了,那麼深拷貝出來的物件也會相應改變。

一、物件引用

物件引用容易理解,直接賦值,修改複製後的陣列,原物件會隨之改變。

//物件引用

var boy = {
    age:18
    }
var girl = boy;
console.log(boy === girl);//true
girl.age = 20;
console.log(boy.age);//20 

理解:使用“=”進行賦值,girl和boy指向了同一內容地址,修改一個,另一個也會修改。

二、淺拷貝

使用Object.assign() 方法用於將所有可列舉屬性的值從一個或多個源物件複製到目標物件。它將返回目標物件。

//淺拷貝
var boy = {
    age:18
    }
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.age = 20;
console.log(boy.age);//18

理解:上述程式碼將原始物件拷貝到一個空物件,就得到原始物件的克隆,原物件和拷貝物件指向不同的記憶體地址,修改原物件和克隆物件,互不影響。

var boy = {
    age:18,
    address:{
        home:'北京'
    }
}
var girl = Object.assign({}, boy);
console.log(boy === girl);//false
girl.address.home = '上海';
console.log(boy.address.home);//上海 

理解:上述程式碼將原始物件拷貝到一個空物件,就得到原始物件的克隆。因為Object.assign()只是淺拷貝girl.address是對棧物件的引用,因此內層物件的修改會影響原始物件。

三、深拷貝

1、JSON.parse()與JSON.stringify()深拷貝

可以通過JSON物件的方法,來進行物件的深拷貝,程式碼如下:

//純資料json物件的深度克隆
function deepClone(obj) {
     return JSON.parse(JSON.stringify(obj));
}

理解:通過物件符串化和字串物件化進行物件的拷貝。此方法只使用與純JSON物件的深拷貝

2、物件遍歷

//包含其他負責的內容 date物件 null undefined
var obj1={
    name:"張三",
    age:20,
    height:[12,26,46],
    address:{
        home:'北京'
    },
    birthday:new Date(),
    father:null,
    mother:undefined,
    school:[
            {
                middleschool:'北大附中',
            },
            {
                university:'清華大學',
            }
        ]
    }
    function clone(obj) { 
        if(obj === null) return null 
        if(typeof obj !== 'object') return obj;
        if(obj.constructor === Date) return new Date(obj); 
        if(obj.constructor === RegExp) return new RegExp(obj);
        var newObj = new obj.constructor ();  //保持繼承鏈
        for (var key in obj) {
         if (obj.hasOwnProperty(key)) {   //不遍歷其原型鏈上的屬性
              var val = obj[key];
              newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除與函式名的耦合
          }
            }  
            return newObj;  
    }; 
        console.log(obj1);
    console.log(clone(obj1));

理解:

(1)、用 new obj.constructor ()建構函式新建一個空的物件,可以保持原形鏈的繼承;

(2)、用obj.hasOwnProperty(key)來判斷屬性是否來自原型鏈上,因為for..in..也會遍歷其原型鏈上的可列舉屬性。

(3)、函式用到遞迴演算法,在函式有名字,而且名字以後也不會變的情況下,這樣定義沒有問題。但問題是這個函式的執行與函式名 factorial 緊緊耦合在了一起。為了消除這種緊密耦合的現象,需要使用 arguments.callee。

參考:https://www.cnblogs.com/wangyulue/articles/7684515.html

---------------------  作者:可樂6666  來源:CSDN  原文:https://blog.csdn.net/xuexizhe88/article/details/80989813  版權宣告:本文為博主原創文章,轉載請附上博文連結!