返回

探秘 JavaScript 中的浅拷贝与深拷贝

前端

在 JavaScript 中,变量可以存储两种类型的值:基本类型(如数字、字符串、布尔值)和引用类型(如对象、数组、函数)。当对基本类型变量进行赋值时,会创建该值的副本,而对引用类型变量进行赋值时,会创建对该对象的引用。这意味着对引用类型变量的更改也会影响其引用的对象。

浅拷贝 只复制对象的顶层属性,而深拷贝 会复制对象的所有属性,包括嵌套的对象和数组。

实现浅拷贝的两种常见方法

1. 使用扩展运算符(...)

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

const obj2 = { ...obj1 };

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

console.log(obj1); // { name: 'John Doe', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA', zip: '12345' } }
console.log(obj2); // { name: 'John Doe', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA', zip: '12345' } }

2. 使用 Object.assign() 方法

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

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

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

console.log(obj1); // { name: 'John Doe', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA', zip: '12345' } }
console.log(obj2); // { name: 'John Doe', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA', zip: '12345' } }

实现深拷贝的常见方法

1. 使用 JSON.parse() 和 JSON.stringify() 方法

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

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

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

console.log(obj1); // { name: 'John Doe', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA', zip: '12345' } }
console.log(obj2); // { name: 'John Doe', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA', zip: '12345' } }

2. 使用递归函数

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

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

  const newObj = {};

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

  return newObj;
}

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

const obj2 = deepCopy(obj1);

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

console.log(obj1); // { name: 'John Doe', age: 30, address: { street: '123 Main Street', city: 'Anytown', state: 'CA', zip: '12345' } }
console.log(obj2); // { name: 'John Doe', age: 30, address: { street: '456 Elm Street', city: 'Anytown', state: 'CA', zip: '12345' } }

在 JavaScript 中,理解浅拷贝和深拷贝的概念并掌握其实现方法非常重要。这有助于您在编写代码时更好地管理对象和数据结构,避免意外的变量引用和数据修改,从而提高代码的质量和可靠性。