likes
comments
collection
share

深拷贝和浅拷贝:JavaScript 中的对象复制

作者站长头像
站长
· 阅读数 23

在 JavaScript 编程中,处理对象的复制是一个常见的任务。对象拷贝分为两种主要类型:浅拷贝和深拷贝。这两种拷贝方式在处理嵌套对象和数据结构时有不同的行为,因此了解它们的工作原理是非常重要的。

浅拷贝

浅拷贝是一种复制对象的方式,它创建了一个新对象,新对象的属性值是原始对象属性值的引用。这意味着当你修改原始对象或新对象的属性时,两者之间的关联会被保留。

在 JavaScript 中,可以使用多种方法进行浅拷贝:

1. 扩展运算符

const original = { a: 1, b: 2 };
const shallowCopy = { ...original };

2. Object.assign()

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

3. 数组的 slice() 方法

const originalArray = [1, 2, 3];
const shallowCopyArray = originalArray.slice();

深拷贝

深拷贝是一种完全复制对象的方式,它不仅复制对象的属性,还递归地复制嵌套对象的属性。这确保了原始对象与新对象之间的完全隔离。

实现深拷贝可能会涉及递归遍历对象的所有属性,并复制它们的值。以下是一个使用递归的简单深拷贝示例:

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }
  
  let copy = Array.isArray(obj) ? [] : {};
  
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  
  return copy;
}

const original = {
  a: 1,
  b: { c: 2, d: 3 }
};

const deepCopyObj = deepCopy(original);

使用浅拷贝

何时使用浅拷贝:

  1. 需要创建对象的简单副本: 如果你只需要创建一个与原始对象具有相同属性的副本,并且这些属性的值是基本数据类型(如字符串、数字等),那么浅拷贝是一个不错的选择。
  2. 需要保留引用关系: 如果你希望新对象和原始对象之间保持引用关系,以便它们共享相同的引用值,那么浅拷贝可以满足这个需求。
  3. 性能和内存考虑: 浅拷贝通常比深拷贝更高效,因为它只复制对象的引用而不涉及递归复制属性。在处理大型对象或需要频繁拷贝的情况下,浅拷贝可能是更好的选择。

示例场景:

考虑一个对象包含简单属性和数组的情况:

const original = {
  name: 'Alice',
  scores: [85, 90, 78]
};

const shallowCopy = { ...original };

在这个示例中,浅拷贝创建了一个与原始对象具有相同属性和值的对象。修改 shallowCopy 中的简单属性(如 name)不会影响 original,但修改数组 scores 中的元素将会影响。

使用深拷贝

何时使用深拷贝:

  1. 需要创建对象的彻底独立副本: 当你需要创建一个与原始对象完全独立的对象,以便在修改副本时不会影响原始对象,深拷贝是必需的。
  2. 处理嵌套对象或复杂数据结构: 如果原始对象包含嵌套的对象、数组或其他引用类型,而你希望新对象与原始对象在所有层级上都是独立的,那么深拷贝是必要的。
  3. 防止循环引用: 深拷贝能够处理对象之间的循环引用,确保复制过程不会进入无限循环。

示例场景:

考虑一个对象包含嵌套对象和数组的情况:

const original = {
  name: 'Alice',
  address: {
    city: 'New York',
    country: 'USA'
  }
};

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

  let copy = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }

  return copy;
}

const deepCopyObj = deepCopy(original);

在这个示例中,深拷贝创建了一个与原始对象完全独立的新对象,包括嵌套的对象属性。修改 deepCopyObj 不会影响 original

总结

浅拷贝和深拷贝各有其适用的场景。理解你的数据结构、需求和预期的对象副本之间的关系,将帮助你选择正确的拷贝方式。浅拷贝适用于创建属性值是基本数据类型的对象副本,而深拷贝适用于创建与原始对象完全独立的对象副本,特别是在处理嵌套结构、防止循环引用或保持数据完整性时。在实际编程中,你可能会根据不同情况交替使用浅拷贝和深拷贝,以获得最佳结果。

转载自:https://juejin.cn/post/7277831840038879267
评论
请登录