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}

 

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