返回

深拷贝和浅拷贝揭秘:深入浅出理解JavaScript复制的艺术

前端


****


****


值传递与引用传递

在JavaScript中,变量可以存储值类型或引用类型。值类型变量存储的是实际值,如数字、字符串和布尔值。引用类型变量存储的是对对象的引用,而不是对象本身。对象是一种复合数据类型,可以包含多个属性,如名称、年龄和地址。

当我们复制值类型变量时,会创建一个新变量并将其值设置为原变量的值。这意味着新变量和原变量是独立存在的,对新变量的任何修改都不会影响原变量。

let num1 = 10;
let num2 = num1;

num2++;

console.log(num1); // 输出:10
console.log(num2); // 输出:11

当我们复制引用类型变量时,会创建一个新变量并将其值设置为对原变量中对象的引用。这意味着新变量和原变量指向同一个对象,对新变量的任何修改都会影响原变量。

let obj1 = {
  name: "John Doe",
  age: 30
};

let obj2 = obj1;

obj2.name = "Jane Doe";

console.log(obj1.name); // 输出:Jane Doe
console.log(obj2.name); // 输出:Jane Doe

深拷贝与浅拷贝

深拷贝是指复制对象的全部内容,包括所有属性和子对象。浅拷贝是指仅复制对象的引用。

要执行深拷贝,可以使用JavaScript的内置方法JSON.parse(JSON.stringify(obj))。此方法将对象转换为JSON字符串,然后将其解析回对象。由于JSON只支持简单的数据类型,因此JSON.stringify()方法会将对象的所有属性和子对象都转换为JSON字符串。当JSON.parse()方法解析JSON字符串时,它会创建一个新的对象,其中包含所有属性和子对象。

let obj1 = {
  name: "John Doe",
  age: 30,
  address: {
    street: "123 Main Street",
    city: "Anytown",
    state: "CA",
    zip: "12345"
  }
};

let obj2 = JSON.parse(JSON.stringify(obj1));

obj2.name = "Jane Doe";
obj2.address.street = "456 Elm Street";

console.log(obj1.name); // 输出:John Doe
console.log(obj1.address.street); // 输出:123 Main Street
console.log(obj2.name); // 输出:Jane Doe
console.log(obj2.address.street); // 输出:456 Elm Street

要执行浅拷贝,可以使用Object.assign()方法。此方法将一个或多个对象的属性复制到目标对象中。

let obj1 = {
  name: "John Doe",
  age: 30,
  address: {
    street: "123 Main Street",
    city: "Anytown",
    state: "CA",
    zip: "12345"
  }
};

let obj2 = Object.assign({}, obj1);

obj2.name = "Jane Doe";
obj2.address.street = "456 Elm Street";

console.log(obj1.name); // 输出:John Doe
console.log(obj1.address.street); // 输出:123 Main Street
console.log(obj2.name); // 输出:Jane Doe
console.log(obj2.address.street); // 输出:456 Elm Street

何时使用深拷贝何时使用浅拷贝

在大多数情况下,浅拷贝就足够了。浅拷贝的效率更高,因为它只需要复制对象的引用,而不需要复制对象的所有属性和子对象。但是,在某些情况下,我们需要使用深拷贝。

例如,当我们需要复制一个对象,并确保新对象与原对象完全独立时,就需要使用深拷贝。这种情况通常发生在我们需要将对象传递给另一个函数或模块,并且我们不想让该函数或模块对原对象进行修改时。

function modifyObject(obj) {
  obj.name = "Jane Doe";
}

let obj1 = {
  name: "John Doe",
  age: 30
};

let obj2 = JSON.parse(JSON.stringify(obj1));

modifyObject(obj2);

console.log(obj1.name); // 输出:John Doe
console.log(obj2.name); // 输出:Jane Doe

总结

深拷贝和浅拷贝是JavaScript中复制对象或数组的两种主要方式。深拷贝是指复制对象的全部内容,包括所有属性和子对象,而浅拷贝是指仅复制对象的引用。在大多数情况下,浅拷贝就足够了。但是,在某些情况下,我们需要使用深拷贝。