返回

对象深拷贝和浅拷贝:从基础到实践详解

前端

在JavaScript中,变量中包含两种类型的值:基本类型值和引用类型值。基本类型值是指存储在栈中的一些简单数据段,如字符串、数字、布尔值等。引用类型值则是引用类型的实例,它是一个保存在堆内存中的对象,如数组、对象、函数等。

当我们对引用类型值进行赋值时,默认情况下进行的是浅拷贝。浅拷贝只复制对象的引用,而不会复制对象本身。这意味着如果我们对浅拷贝的对象进行修改,原始对象也会受到影响。

而深拷贝则不同,它会复制对象的整个值,包括对象的所有属性和方法。这样,即使我们对深拷贝的对象进行修改,原始对象也不会受到影响。

浅拷贝的实现

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

const obj2 = obj1; // 浅拷贝

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

console.log(obj1); // { name: 'Jane', age: 30, address: { street: '456 Elm St', city: 'Anytown', state: 'CA' } }

在这个例子中,我们对对象obj1进行了浅拷贝,并将其赋值给了obj2。然后,我们修改了obj2的name属性和address.street属性。最后,我们打印obj1,可以看到obj1的name属性和address.street属性也被修改了。这是因为浅拷贝只复制了对象的引用,而没有复制对象本身。

深拷贝的实现

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

const obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝

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

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

在这个例子中,我们对对象obj1进行了深拷贝,并将其赋值给了obj2。然后,我们修改了obj2的name属性和address.street属性。最后,我们打印obj1,可以看到obj1的name属性和address.street属性没有被修改。这是因为深拷贝复制了对象的整个值,包括对象的所有属性和方法。

浅拷贝和深拷贝的优缺点

浅拷贝和深拷贝各有其优缺点,具体情况需要根据具体需求选择合适的拷贝方式。

浅拷贝的优点:

  • 速度快,因为只需要复制对象的引用。
  • 内存占用少,因为不需要复制对象本身。

浅拷贝的缺点:

  • 如果修改浅拷贝的对象,原始对象也会受到影响。
  • 不能复制对象中的循环引用。

深拷贝的优点:

  • 修改深拷贝的对象,不会影响原始对象。
  • 可以复制对象中的循环引用。

深拷贝的缺点:

  • 速度慢,因为需要复制对象本身。
  • 内存占用多,因为需要复制对象本身。

总结

对象深拷贝和浅拷贝是两种重要的拷贝方式,它们各有其优缺点。在实际开发中,需要根据具体需求选择合适的拷贝方式。