JS的淺拷貝和深拷貝

最近在開發中遇到一個小問題,就是因爲js的淺拷貝致使變量被污染,忽然發現對於js的變量值傳遞和引用傳值並無特別注意,現在總結以下,以備來者考慮。es6

JS的變量分普通類型和引用類型,具體以下:ui

 基本數據類型:StringBooleanNumberUndefinedNullspa

 引用數據類型:Object(ArrayDateRegExpFunction)prototype

 

對於普通類型的變量賦值都是值傳遞,而引用類型變量的賦值。例以下面的代碼:指針

      

        var b = 3;

        var c = b;

        b = 2;

        console.log(b); // 2

        console.log(c); // 3

 

普通的數據類型變量的賦值,只是值傳遞,變量之間互不影響。而引用類型不一樣:code

        

        var MyObj = {

            price: "200.00",

            count: 24

        };

        var Gift = MyObj;

        MyObj.price = "300.00";

        console.log(Gift.price);  // 300.00

        console.log(MyObj.price); // 300.00

 

 

因此這種引用類型變量的複製是被稱爲淺拷貝:新變量的指針指向被複制的變量,當被複制的變量發生變化,新變量也會隨着改變。而咱們工做實際中是須要徹底拷貝一個變量,一個完整備份,這就是深拷貝。blog

 

簡單來講,深淺拷貝的原理圖以下:遞歸

   

因此問題來了,怎麼才能實現深拷貝的。開發

兩種途徑,一種本身使用遞歸的方式去作深拷貝,一種使用第三方庫或者es原生實現。io

es6的方式最簡單,結合遞歸代碼以下:

// 遞歸方式實現深拷貝
function DeepCopy(obj) {
    var return_obj = {};

    for (let key in obj) {
       if (Object.prototype.toString.call(obj[key]) === '[Object Object]') {
         return_obj[key] = DeepCopy(obj[key]);  
       } else {
        return_obj[key] = {...obj[key]};  // es6語法糖,處理當前層次賦值爲深拷貝
       }

   }
   return return_obj;
}

 

第三方庫能夠使用loadash

var _ = require('lodash');

var obj1 = {    a: 1,    b: { f: { g: 1 } },    c: [1, 2, 3] };

var obj2 = _.cloneDeep(obj1);

console.log(obj1.b.f === obj2.b.f); // false
相關文章
相關標籤/搜索