返回

深拷贝 vs 浅拷贝:JS 实现深浅拷贝的几种方法

前端

什么是深拷贝和浅拷贝?

在 JavaScript 中,变量包含两种不同数据类型的值:基本类型和引用类型。基本类型值是独立的,而引用类型值则是对另一个值的引用。当我们将一个基本类型值赋给变量时,该变量将包含该值的一个副本。然而,当我们将一个引用类型值赋给变量时,该变量将包含对该值的引用。这意味着如果我们修改变量的值,我们也将修改原始值。

深拷贝和浅拷贝是两种不同的方法来复制引用类型值。浅拷贝只复制引用类型值的引用,而深拷贝则复制引用类型值及其所有属性。

浅拷贝

浅拷贝是复制引用类型值最简单的方法。我们可以使用赋值运算符 (=) 来进行浅拷贝。例如,如果我们有一个对象 a,我们可以使用以下代码来创建一个对象的浅拷贝 b

const a = {
  name: 'John',
  age: 30,
  address: {
    street: '123 Main Street',
    city: 'New York',
    state: 'NY'
  }
};

const b = a;

现在,ba 都指向同一个对象。这意味着如果我们修改 b 中的任何属性,a 中的属性也会被修改。例如,如果我们将 b.name 修改为 'Jane' a.name 也会变为 'Jane'

深拷贝

深拷贝是复制引用类型值的一种更复杂的方法。我们需要遍历引用类型值的所有属性,并为每个属性创建一个新的副本。我们可以使用递归来实现深拷贝。例如,如果我们有一个对象 a,我们可以使用以下代码来创建一个对象的深拷贝 b

const a = {
  name: 'John',
  age: 30,
  address: {
    street: '123 Main Street',
    city: 'New York',
    state: 'NY'
  }
};

const b = deepCopy(a);

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  if (Array.isArray(obj)) {
    return obj.map(deepCopy);
  }

  const newObj = {};
  for (const key in obj) {
    newObj[key] = deepCopy(obj[key]);
  }

  return newObj;
}

现在,ba 是两个完全独立的对象。这意味着如果我们修改 b 中的任何属性,a 中的属性不会被修改。例如,如果我们将 b.name 修改为 'Jane' a.name 仍然是 'John'

深拷贝和浅拷贝的使用场景

深拷贝和浅拷贝都有各自的使用场景。浅拷贝通常用于复制不需要修改的数据,例如函数参数或临时变量。深拷贝通常用于复制需要修改的数据,例如对象或数组。

深拷贝和浅拷贝的优缺点

深拷贝和浅拷贝都有各自的优缺点。深拷贝的优点是它可以复制引用类型值的所有属性,而浅拷贝的优点是它更简单、更高效。

JS 实现深浅拷贝的几种方法

除了上述的递归方法之外,我们还可以使用其他方法来实现深浅拷贝。这些方法包括:

  • 使用 JSON.parse()JSON.stringify()
  • 使用 Object.assign()
  • 使用第三方库,如 lodashramda

结论

在本文中,我们探讨了深拷贝和浅拷贝之间的区别,以及在 JavaScript 中实现深浅拷贝的几种方法。我们还讨论了深拷贝和浅拷贝的使用场景,以及每种方法的优缺点。