浅拷贝和深拷贝

100 阅读2分钟

在 JavaScript 中,浅拷贝和深拷贝是两种不同的方式来复制对象或数组的内容。它们在复制嵌套对象或数组时表现出不同的行为。

浅拷贝

复制后的对象会与原对象共用内存地址,会互相干扰

常用浅拷贝

let a = {
    age: 20
};

let b = a;

b.age = 30;

console.log(a.age); // 30

使用 Object.assign() 进行浅拷贝

const originalObject = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, originalObject);

console.log(shallowCopy); // { a: 1, b: { c: 2 } }

shallowCopy.a = 100; // 修改复制后的对象的属性
shallowCopy.b.c = 200; // 修改复制后对象的嵌套对象属性

console.log(originalObject); // { a: 1, b: { c: 200 } }
console.log(shallowCopy); // { a: 100, b: { c: 200 } }

在上面的示例中,Object.assign() 创建了 shallowCopy,但它仍然引用了 originalObject 中的嵌套对象。

深拷贝

复制的对象会创建一个新的内存地址,原对象内存地址的属性会复制到新对象的内存地址,互不干扰

利用JSON类

就是将一个对象转为JSON字符串,再转回JSON对象

let a = {
    age: 20
};

let b = JSON.parse(JSON.stringify(a));
console.log(b.age); // 20

b.age = 30;

console.log(a.age); // 20
console.log(b.age); // 3

  • 优点:方便快捷,性能相对比较好
  • 缺点:复杂的对象进行JSON转换有可能会丢失属性,如下代码
let a = {
    age: 20,
    local: function() {
        return 5;
    }
};

let b = JSON.parse(JSON.stringify(a));

console.log(b); // { age : 20 }
console.log(b.local()); //  b.loacl is not a function

使用递归进行深拷贝

以下是一个简单的深拷贝示例,使用递归方法:

function deepClone(obj) {
    if (obj === null || typeof obj !== "object") {
        return obj; // 如果是基本类型或 null,则直接返回
    }

    if (Array.isArray(obj)) {
        // 如果是数组,递归复制每个元素
        return obj.map(item => deepClone(item));
    }

    // 如果是对象,递归复制每个属性
    const clonedObj = {};
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            clonedObj[key] = deepClone(obj[key]);
        }
    }

    return clonedObj;
}

const originalObject = { a: 1, b: { c: 2 } };
const deepCopy = deepClone(originalObject);

console.log(deepCopy); // { a: 1, b: { c: 2 } }

deepCopy.a = 100; // 修改复制后的对象的属性
deepCopy.b.c = 200; // 修改复制后对象的嵌套对象属性

console.log(originalObject); // { a: 1, b: { c: 2 } }
console.log(deepCopy); // { a: 100, b: { c: 200 } }

在上述示例中,deepClone 函数递归地复制对象及其嵌套结构,创建一个完全独立的深拷贝。

需要注意的是,深拷贝可能会更消耗内存和计算资源,特别是在处理大型嵌套结构时。因此,在选择浅拷贝和深拷贝之间,需要根据具体需求权衡性能和复制结果。如果确实需要完全独立的副本,那么深拷贝是合适的选择。