Javascript中的深複製和淺複製

棧內存和堆內存

JavaScript中的數據類型可分爲值類型引用類型,值類型變量的值直接存放在棧內存中,引用類型變量在棧內存中存儲的是相應的堆內存的地址,堆內存中存放引用類型變量的具體內容

值類型變量的複製會在棧內開闢一個和原變量大小一樣的新空間,然後將原變量的內容複製一份放到這個新的空間內,所以新變量與原變量是分開的,互不影響。

深複製和淺複製是針對引用類型來說的

淺複製( Shallow Copy )

淺複製,只是複製棧內存中的堆內存地址

let arr1 = [];
for (let i = 0; i < 100; ++i) {
    arr1[i] = i+1;
}
let arr2 = arr1;
arr1[0] = 400;
console.log(arr2[0]);     // 400

arr1和arr2指向同一片內存地址,所以arr1和arr2的改變會互相影響

深複製( Deep Copy )

實現對目標的完全複製

function copy (a, b) {
    for (var i = 0; i < a.length; ++i) {
        b[i] = a[i];
    }
}

let arr1 = [];
for (let i = 0; i < 100; ++i) {
    arr1[i] = i+1;
}
var arr2 = [];
copy(arr1, arr2);
arr1[0] = 400;
console.log(arr2[0]);     // 1

複製完成後,arr1和arr2互不影響 

Array.concat()和Array.slice()、ES6的...擴展運算符、Object.assign():

只對第一層進行深複製

const arr1 = [1,2,3,4,5];
const arr2 = arr1.slice();

const arr3 = [[1,2],3,4,5]
const arr4 = arr3.slice();


arr2[0] = 100; 
console.log(arr1[0]);         // 1

arr4[0][0] = 100;
console.log(arr3[0][0]);        // 100

JSON.stringfy()可以實現深複製但對目標有要求

const arr1 = [1,2,3,4,5];
const arr2 = JSON.parse(JSON.stringify(arr1));

arr2[0] = 100;   
console.log(arr1[0])        // 1

If undefined, a function, or a symbol is encountered during conversion it is either omitted (when it is found in an object) or censored to null (when it is found in an array). JSON.stringify can also just return undefined when passing in "pure" values like JSON.stringify(function(){}) or JSON.stringify(undefined)

也就是說undefined,function,symbol在轉換過程中會被忽略,而且原對象constructor會被改成Object,所以如果目標中有function就不適用

const obj1 = {
    a:1,
    fn:function () {
        console.log('test');
    }
}
const obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2);       // {a: 1}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章