返回

「JavaScript进阶」一文吃透深浅拷贝

前端

在我们编写的JavaScript程序中,常常会遇到一些问题,比如:如何将一个对象的属性值拷贝到另一个对象中?如何确保在修改一个对象的属性值时,不会影响另一个对象的属性值?这些问题都与JavaScript中的拷贝操作有关。

在JavaScript中,拷贝操作分为两种:深拷贝和浅拷贝。深拷贝是指将一个对象的属性值和子属性值都拷贝到另一个对象中,而浅拷贝是指仅将一个对象的属性值拷贝到另一个对象中,但不拷贝子属性值。

浅拷贝

浅拷贝是一种简单的拷贝操作,它仅将一个对象的属性值拷贝到另一个对象中。这可以通过使用赋值运算符(=)来实现。

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

const obj2 = obj1;

obj2.name = 'Jane Doe';

console.log(obj1); // { name: 'Jane Doe', age: 30 }

在这个示例中,我们将obj1的属性值拷贝到obj2中。然后,我们修改了obj2的name属性值。这时,我们发现obj1的name属性值也发生了变化。这是因为浅拷贝只拷贝了obj1的属性值,并没有拷贝子属性值。因此,当我们修改obj2的name属性值时,也会影响obj1的name属性值。

深拷贝

深拷贝是一种更复杂的拷贝操作,它将一个对象的属性值和子属性值都拷贝到另一个对象中。这可以通过使用递归函数或JSON.parse()和JSON.stringify()函数来实现。

// 使用递归函数实现深拷贝
function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

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

const obj2 = deepCopy(obj1);

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

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

在这个示例中,我们使用递归函数实现了深拷贝。我们将obj1的属性值和子属性值都拷贝到obj2中。然后,我们修改了obj2的name属性值和address.street属性值。这时,我们发现obj1的属性值没有发生变化。这是因为深拷贝将obj1的属性值和子属性值都拷贝到obj2中,因此修改obj2的属性值不会影响obj1的属性值。

什么时候使用深拷贝,什么时候使用浅拷贝?

浅拷贝和深拷贝各有其优缺点。浅拷贝简单易用,但它只拷贝对象本身的属性值,不会拷贝子属性值。深拷贝更复杂一些,但它会拷贝对象本身的属性值和子属性值。

在实际开发中,我们通常会根据需要选择使用浅拷贝还是深拷贝。如果我们只需要拷贝对象本身的属性值,那么可以使用浅拷贝。如果我们需要拷贝对象本身的属性值和子属性值,那么可以使用深拷贝。

例如,如果我们要拷贝一个表单中的数据,那么可以使用浅拷贝。因为表单中的数据都是基本数据类型,浅拷贝就可以满足我们的需要。如果我们要拷贝一个包含复杂对象的JSON对象,那么可以使用深拷贝。因为JSON对象包含子对象,浅拷贝无法满足我们的需要。