返回

揭秘前端面试大杀器:浅拷贝、简易深拷贝和完整深拷贝

前端

JavaScript 浅拷贝、简易深拷贝和完整深拷贝

浅拷贝

浅拷贝是一种创建对象副本的方法,只复制对象的浅层属性,不会复制嵌套的对象或数组。它使用 Object.assign() 方法或扩展运算符(...)来实现。浅拷贝常用于需要创建一个对象的新实例并修改其某些属性,但又不想影响原始对象的情况。

const obj1 = {
  name: 'John',
  address: {
    street: '123 Main Street',
    city: 'New York'
  }
};

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

obj2.name = 'Jane';
obj2.address.street = '456 Elm Street';

console.log(obj1); // { name: 'John', address: { street: '456 Elm Street', city: 'New York' } }
console.log(obj2); // { name: 'Jane', address: { street: '456 Elm Street', city: 'New York' } }

在这个示例中,obj2obj1 的浅拷贝。当我们修改 obj2 的属性时,obj1 的属性也会被修改,因为它们指向同一个内存地址。

简易深拷贝

简易深拷贝是一种创建对象副本的方法,会复制对象的全部属性,包括嵌套的对象和数组。它使用 JSON.parse(JSON.stringify()) 方法来实现。简易深拷贝常用于需要创建一个对象的新实例并修改其任何属性,而不影响原始对象的情况。

const obj1 = {
  name: 'John',
  address: {
    street: '123 Main Street',
    city: 'New York'
  }
};

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

obj2.name = 'Jane';
obj2.address.street = '456 Elm Street';

console.log(obj1); // { name: 'John', address: { street: '123 Main Street', city: 'New York' } }
console.log(obj2); // { name: 'Jane', address: { street: '456 Elm Street', city: 'New York' } }

在这个示例中,obj2obj1 的简易深拷贝。当我们修改 obj2 的属性时,obj1 的属性不会被修改,因为它们指向不同的内存地址。

完整深拷贝

完整深拷贝是一种创建对象副本的方法,会递归复制对象的全部属性,包括嵌套的对象和数组及其属性。它使用递归算法来实现。完整深拷贝常用于需要创建一个对象的新实例并修改其任何属性,而不影响原始对象,并且要保持所有嵌套属性之间的关联的情况。

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;
}

const obj1 = {
  name: 'John',
  address: {
    street: '123 Main Street',
    city: 'New York'
  }
};

const obj2 = deepCopy(obj1);

obj2.name = 'Jane';
obj2.address.street = '456 Elm Street';

console.log(obj1); // { name: 'John', address: { street: '123 Main Street', city: 'New York' } }
console.log(obj2); // { name: 'Jane', address: { street: '456 Elm Street', city: 'New York' } }

在这个示例中,obj2obj1 的完整深拷贝。当我们修改 obj2 的属性时,obj1 的属性不会被修改,因为它们指向不同的内存地址,并且嵌套属性之间的关联也保持不变。

总结

浅拷贝、简易深拷贝和完整深拷贝是 JavaScript 中用于创建对象副本的三种方法,每个方法都有其特定的用途和特点。浅拷贝只复制对象的浅层属性,简易深拷贝复制对象的全部属性,而完整深拷贝则递归复制对象的全部属性。根据不同的需求,选择适当的拷贝方法对于防止对象之间的意外修改和保持数据完整性至关重要。

常见问题解答

  1. 什么时候应该使用浅拷贝?

    • 当需要创建一个对象的新实例并修改其某些属性,但又不想影响原始对象时。
  2. 什么时候应该使用简易深拷贝?

    • 当需要创建一个对象的新实例并修改其任何属性,而不影响原始对象的情况。
  3. 什么时候应该使用完整深拷贝?

    • 当需要创建一个对象的新实例并修改其任何属性,而不影响原始对象,并且要保持所有嵌套属性之间的关联时。
  4. 浅拷贝和深拷贝之间的主要区别是什么?

    • 浅拷贝只复制对象的浅层属性,而深拷贝复制对象的全部属性,包括嵌套的对象和数组。
  5. 如何实现完整深拷贝?

    • 使用递归算法来遍历对象及其所有嵌套属性,并为每个属性创建一个新的副本。