返回

浅拷贝与深拷贝:理解两种拷贝的区别并避免意外错误

前端

浅拷贝与深拷贝

在计算机科学中,拷贝是创建另一个已存在对象的副本。这种副本可以是浅拷贝或深拷贝。浅拷贝只拷贝对象本身,而深拷贝会递归地拷贝对象及其所有属性。

浅拷贝

浅拷贝只拷贝对象本身,而不会拷贝它的属性。这意味着当您对浅拷贝进行更改时,不会影响原始对象。浅拷贝可以通过使用赋值运算符(=)或 Object.assign() 方法来创建。

例如,以下代码创建了一个对象的浅拷贝:

const originalObject = {
  name: 'John Doe',
  age: 30
};

const浅拷贝 = Object.assign({}, originalObject);

浅拷贝.name = 'Jane Doe';

console.log(originalObject); // { name: 'John Doe', age: 30 }
console.log(浅拷贝); // { name: 'Jane Doe', age: 30 }

如您所见,当我们更改浅拷贝的名称时,原始对象不会受到影响。这是因为浅拷贝只拷贝了对象的本身,而没有拷贝它的属性。

深拷贝

深拷贝会递归地拷贝对象及其所有属性。这意味着当您对深拷贝进行更改时,原始对象也会受到影响。深拷贝可以通过使用 JSON.parse() 和 JSON.stringify() 方法来创建。

例如,以下代码创建了一个对象的深拷贝:

const originalObject = {
  name: 'John Doe',
  age: 30
};

const深拷贝 = JSON.parse(JSON.stringify(originalObject));

深拷贝.name = 'Jane Doe';

console.log(originalObject); // { name: 'Jane Doe', age: 30 }
console.log(深拷贝); // { name: 'Jane Doe', age: 30 }

如您所见,当我们更改深拷贝的名称时,原始对象也会受到影响。这是因为深拷贝递归地拷贝了对象及其所有属性。

何时使用浅拷贝和深拷贝

浅拷贝通常用于创建对象的新副本,而无需更改原始对象。例如,您可能想要创建对象的一个副本以将其传递给另一个函数,而无需担心对原始对象进行更改。

深拷贝通常用于创建对象的新副本,并确保更改该副本不会影响原始对象。例如,您可能想要创建对象的一个副本以将其存储在数据库中,而无需担心对原始对象进行更改。

如何在 JavaScript 中实现深拷贝

有几种方法可以在 JavaScript 中实现深拷贝。最简单的方法是使用 JSON.parse() 和 JSON.stringify() 方法。如下所示:

function deepCopy(object) {
  return JSON.parse(JSON.stringify(object));
}

您也可以使用递归函数来实现深拷贝。如下所示:

function deepCopy(object) {
  if (Array.isArray(object)) {
    return object.map(deepCopy);
  } else if (typeof object === 'object') {
    return Object.keys(object).reduce((acc, key) => {
      acc[key] = deepCopy(object[key]);
      return acc;
    }, {});
  } else {
    return object;
  }
}

避免意外错误

在使用浅拷贝和深拷贝时,需要注意一些潜在的错误。

首先,当您对浅拷贝进行更改时,可能会意外地更改原始对象。例如,如果您不小心将浅拷贝的属性设置为 null,则原始对象的属性也将设置为 null。

其次,当您对深拷贝进行更改时,可能会意外地更改原始对象的属性。例如,如果您不小心将深拷贝的数组元素设置为 null,则原始对象的数组元素也将设置为 null。

最后,当您使用 JSON.parse() 和 JSON.stringify() 方法进行深拷贝时,可能会丢失某些信息。例如,如果您深拷贝一个日期对象,则日期对象的原始值将丢失。

要避免这些错误,请务必注意您何时使用浅拷贝和深拷贝。如果您不确定应该使用哪种拷贝,则最好使用深拷贝。