返回

打破浅层次拷贝的限制:深拷贝的本质探索

前端

浅尝辄止的浅拷贝

浅拷贝只复制对象本身的属性值,而不会复制其子对象的属性值。这种方式在处理简单的数据类型(如数字、字符串)时非常有效。然而,当处理复杂的数据结构(如对象、数组)时,浅拷贝就会遇到问题。

举个例子

// 浅拷贝
const person1 = {
    name: "John Doe",
    address: {
        street: "123 Main Street",
        city: "Anytown",
        state: "CA",
        zip: "12345"
    }
};

// 创建 person2,并将其值设置为 person1 的浅拷贝
const person2 = {...person1};

// 修改 person2 的 address.city
person2.address.city = "Newtown";

// 输出 person1 和 person2
console.log(person1);
console.log(person2);

运行这段代码,你会发现 person1 和 person2 的 address 对象指向同一个内存地址。这意味着修改 person2 的 address.city 属性也会影响 person1 的 address.city 属性。

深层次探索的深拷贝

深拷贝创建新对象并将其所有属性值拷贝到新对象中,而不会复制其子对象的引用。这样,修改新对象的属性值不会影响原始对象。

为了实现深拷贝,可以使用递归算法。递归算法是指函数调用自身的一种方式。在深拷贝的上下文中,这意味着递归地复制对象的所有属性值,包括子对象的属性值。

以下是如何使用递归实现深拷贝的示例代码

// 深拷贝
const deepCopy = (obj) => {
    // 如果对象是基本类型(如数字、字符串),则直接返回该对象
    if (typeof obj === "number" || typeof obj === "string") {
        return obj;
    }

    // 创建新对象
    const newObj = Array.isArray(obj) ? [] : {};

    // 递归地复制对象的所有属性值,包括子对象的属性值
    for (const key in obj) {
        newObj[key] = deepCopy(obj[key]);
    }

    return newObj;
};

// 测试深拷贝
const person1 = {
    name: "John Doe",
    address: {
        street: "123 Main Street",
        city: "Anytown",
        state: "CA",
        zip: "12345"
    }
};

// 创建 person2,并将其值设置为 person1 的深拷贝
const person2 = deepCopy(person1);

// 修改 person2 的 address.city
person2.address.city = "Newtown";

// 输出 person1 和 person2
console.log(person1);
console.log(person2);

运行这段代码,你会发现 person1 和 person2 的 address 对象指向不同的内存地址。这意味着修改 person2 的 address.city 属性不会影响 person1 的 address.city 属性。

深拷贝的应用场景

深拷贝在编程中有很多应用场景,例如:

  • 当你想复制一个对象而又不影响原始对象时
  • 当你想将对象传递给另一个函数,而又不希望该函数修改该对象时
  • 当你想将对象存储在数据库中时

结论

理解浅拷贝和深拷贝之间的差异对于编程非常重要。浅拷贝只复制对象本身的属性值,而不会复制其子对象的属性值。深拷贝则创建新对象并将其所有属性值拷贝到新对象中,而不会复制其子对象的引用。可以使用递归算法来实现深拷贝。深拷贝在编程中有很多应用场景,例如:当你想复制一个对象而又不影响原始对象时,当你想将对象传递给另一个函数,而又不希望该函数修改该对象时,当你想将对象存储在数据库中时。