返回

浅拷贝的坑,你掉过吗?

前端

在JavaScript中,浅拷贝(shallow copy)是一种快速而简单的对象复制方式。它可以将一个对象的所有基本类型属性的值复制到另一个对象中,但不会复制引用类型属性的值。这意味着,如果一个对象的属性是另一个对象,那么浅拷贝只会复制对该对象的引用,而不是复制该对象本身。

在某些情况下,浅拷贝可能并不是最好的选择。例如,如果要复制一个包含引用类型属性的对象,那么浅拷贝可能会导致问题。这是因为,浅拷贝只复制了对该属性的引用,而不是复制该属性本身。这意味着,如果稍后更改了该属性的值,那么两个对象都将受到影响。

为了避免这个问题,可以使用深拷贝(deep copy)来复制对象。深拷贝会复制对象的所有属性,包括引用类型属性。这意味着,即使稍后更改了某个引用类型属性的值,也不会影响另一个对象。

虽然深拷贝在某些情况下更安全,但它也比浅拷贝慢,而且可能需要更多的内存。因此,在选择使用哪种复制方式时,需要权衡利弊。

为了帮助读者更好地理解浅拷贝和深拷贝的区别,我们来看几个经典的面试题:

  1. 以下代码会输出什么?
const obj = {
  name: 'John',
  address: {
    street: '123 Main Street',
    city: 'Anytown',
    state: 'CA'
  }
};

const copy = Object.assign({}, obj);

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

console.log(obj.address.street); // 123 Main Street
console.log(copy.address.street); // 456 Elm Street

答案:

这段代码使用Object.assign()函数来创建obj的浅拷贝。Object.assign()函数只复制obj的基本类型属性的值,不复制引用类型属性的值。因此,当更改copy.address.street的值时,obj.address.street的值不会受到影响。

  1. 以下代码会输出什么?
const obj = {
  name: 'John',
  address: {
    street: '123 Main Street',
    city: 'Anytown',
    state: 'CA'
  }
};

const copy = JSON.parse(JSON.stringify(obj));

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

console.log(obj.address.street); // 123 Main Street
console.log(copy.address.street); // 456 Elm Street

答案:

这段代码使用JSON.parse()JSON.stringify()函数来创建obj的深拷贝。JSON.stringify()函数将obj转换成一个JSON字符串,然后JSON.parse()函数将JSON字符串转换成一个新的对象。这个新对象是obj的深拷贝,因为JSON.stringify()JSON.parse()函数会递归地复制obj的所有属性,包括引用类型属性。因此,当更改copy.address.street的值时,obj.address.street的值不会受到影响。

通过这两个例子,我们可以看到浅拷贝和深拷贝的区别。浅拷贝只复制基本类型属性的值,不复制引用类型属性的值。深拷贝复制所有属性,包括引用类型属性的值。在选择哪种复制方式时,需要根据具体情况权衡利弊。