JavaScript中的深拷贝和浅拷贝

概述

  • 基本类型存储在栈内存中,假如 var a = 1,如果复制var b = a;则表示也给b创建了内存空间,因此操作b时并不会影响a;
  • 引用类型是将值存储在堆内存中,而将名字存在栈内存中,并且栈内存会提供一个引用的地址,指向堆内存;
  • 基本类型没有深拷贝和浅拷贝的概念,这个概念只针对于Object、Array、Function等这类引用类型的数据。
  • 浅拷贝只是在栈内存了拷贝了引用的地址;而深拷贝是在堆内存中开辟了。

实现深拷贝

1. 递归复制所有层级的属性

function deepClone(obj) {
    let cloneRes = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj === 'object') {
        for(let key in obj) {
            
            if (obj[key] && typeof obj[key] === 'object') {
                cloneRes[key] = deepClone(obj[key]);
            } else {
                cloneRes[key] = obj[key];
            }
        }
        
    } else {
        cloneRes = obj;
    }
    return cloneRes;
}

2. 利用JSON对象的parse和stringify

var arr = [1,2,[3,4]];
var arr2 = JSON.parse(JSON.stringify(arr));

!!这些不是深拷贝

1.Object.assign()

// 如果被拷贝对象只有一层属性,就是深拷贝,第二层以后就是浅拷贝
var obj = {a: 1, b: 2};
var obj2 = Object.assign({},obj);
obj2.c = 3; // obj = {a: 1, b: 2};  obj2 = {a: 1, b: 2, c:3}

var obj3 = {a: 1, b: 2, c: 3, d: {inner:90}};
var obj4 = Object.assign({}, obj3);
obj4.c = 'c';
obj4.d.inner2 = 100;
// obj3 = {a: 1, b: 2, c: 3, d: {inner:90, inner2: 100}};
// obj3 = {a: 1, b: 2, c: c, d: {inner:90, inner2: 100}};
--------------------------------------------------

Object.assign语法,可以用于合并函数:
Object.assign(target, source1,source2...);  // target: 目标对象; source:源对象,返回目标对象

2.slice()

// 被拷贝数组只有一层,就是浅拷贝,第二层以后就是深拷贝
var arr = [1,2,3];
var arr2 = arr.slice();
arr2.push(4);   // arr: [1,2,3]; arr2:[1,2,3,4];

var arr = [1,2,[3,4]];
var arr2 = arr.slice();
arr2[2][1] = 5; 
arr2.push(6);   // arr:[1,2,[3,5]]; arr2:[1,2,[3,5], 6]

3. 展开运算符

和Object一样,只有第一层是深拷贝,第二层开始就是浅拷贝

var obj5 = {...obj4};
obj5.c = 'c5';
obj5.d.inner5 = 101;
// obj4 = {a: 1, b: 2, c: "c", d: {inner:90,inner2:100,inner5:101}}
// obj5 = {a: 1, b: 2, c: "c5", d: {inner:90,inner2:100,inner5:101}}

你可能感兴趣的:(JavaScript中的深拷贝和浅拷贝)