js 數組對象深拷貝

結論:對象的拷貝不能采用直接賦值的方式。

背景

踩過的坑如下:

formData本來是父組件傳過來的,但是我不想直接用,于是我直接賦值給一個formDataCopy的對象。

但是詭異的事情發生了,就是在我填寫自己的表單組件的時候,一旦表單的數據發生的變化時,本來是formDataCopy的值發生變化,但是‘formDataDefault值’ 這個字符串卻被打印出來,也就是說formData改變了。

奇怪,formData是父組件傳過來的值怎么會改變呢?

經過一番掙扎,才發現formDataCopy使用的是簡單的賦值,導致formDataCopy和formData指向相同的對象。

formDataCopy一改變,formData就會跟著變。

以上是背景,所以我就對淺拷貝和深拷貝進行了總結:

淺拷貝

什么是淺拷貝:兩者是指向一個對象。

對象的淺拷貝

1、對象的直接遍歷賦值。

2、ES6中的 var copyObj = Object.assign({}, obj);

3、ES7擴展運算符 var copyObj = { ...obj }

4、Jquery淺拷貝 var copiedObject = jQuery.extend({}, originalObject) 如果改變了originalObject,copiedObject 也會變。

數組的淺拷貝

(兩者指向不同的對象,但是只能拷貝一層)

  • array.concat();
  • array.slice(0);

如果該元素是個對象引用 (不是實際的對象),slice 會拷貝這個對象引用到新的數組里。兩個對象引用都引用了同一個對象。如果被引用的對象發生改變,則新的和原來的數組中的這個元素也會發生改變,所以是淺拷貝。

對于字符串、數字及布爾值來說(不是 String、Number 或者 Boolean 對象),slice 會拷貝這些值到新的數組里。在別的數組里修改這些字符串或數字或是布爾值,將不會影響另一個數組。

也就是說,如果原數組改變的是基本數據類型,比如String,Boolean,Number的數據,不會影響到新數組;
但是如果改變的是對象或者數組中的數據,是會影響到新數組的,也也就是對于對象或者數組,新舊數組指向的是一個對象。

深拷貝

(下面說的深拷貝是基本對象的深拷貝,不考慮對象的復雜屬性,比如set,get,Function等)

1、最簡單的方式 JSON.parse(JSON.stringify(Obj)) 這種方法使用較為簡單,可以滿足基本的深拷貝需求,而且能夠處理JSON格式能表示的所有數據類型,但是對于正則表達式類型、函數類型等無法進行深拷貝(而且會直接丟失相應的值)。

2、jQuery深拷貝 var copiedObject = $.extend(true, {}, originalObject)

3、手動寫遞歸方式

var array = [
   { number: 1 },
   { number: 2 },
   { number: 3 }
];
function copy (obj) {
        var newobj = obj.constructor === Array ? [] : {};
        if(typeof obj !== 'object'){
            return;
        }
        for(var i in obj){
           newobj[i] = typeof obj[i] === 'object' ? copy(obj[i]) : obj[i];
        }
        return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); //  [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]

參考文檔

//www.eoxav.com/penghuwan/p/7359026.html

https://github.com/wengjq/Blog/issues/3

posted @ 2019-08-11 12:50 Daotin 閱讀(...) 評論(...) 編輯 收藏