JS的淺拷貝和深拷貝


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

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

 基本數據類型:StringBooleanNumberUndefinedNull

 引用數據類型:Object(ArrayDateRegExpFunction)

 

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

      

        var b = 3;

        var c = b;

        b = 2;

        console.log(b); // 2

        console.log(c); // 3

 

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

        

        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

 

 

所以這種引用類型變量的復制是被稱為淺拷貝:新變量的指針指向被復制的變量,當被復制的變量發生變化,新變量也會隨着改變。而我們工作實際中是需要完全拷貝一個變量,一個完整備份,這就是深拷貝。

 

簡單來說,深淺拷貝的原理圖如下:

   

所以問題來了,怎么才能實現深拷貝的。

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

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM