返回

高阶JavaScript四部曲:1深浅拷贝:就如你想象的那样,完全操控JavaScript!

前端

浅拷贝与深拷贝:JavaScript 中的对象复制详解

在 JavaScript 开发中,对对象进行复制是常见操作,但了解不同复制方法之间的细微差别至关重要。浅拷贝和深拷贝是 JavaScript 中用来复制对象的两种基本技术,它们在复制过程和影响上有显著差异。

浅拷贝

浅拷贝 涉及复制对象属性的值,如果属性值是简单类型(例如字符串或数字),则复制实际值。但是,如果属性值是引用类型(例如数组或对象),则浅拷贝只会复制该属性的内存地址。因此,原始对象和副本指向相同的底层数据结构。

const obj1 = {
  name: '张三',
  age: 20,
  friends: ['李四', '王五']
};

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

console.log(obj2); // { name: '张三', age: 20, friends: ['李四', '王五'] }

obj2.name = '李四';
obj2.friends.push('赵六');

console.log(obj1); // { name: '李四', age: 20, friends: ['李四', '王五', '赵六'] }

在这个示例中,obj1obj2 都是引用类型,obj2obj1 的浅拷贝。当修改 obj2 的属性或属性值时,obj1 也受到影响。这是因为浅拷贝仅复制了属性的值,而没有复制对象本身。

深拷贝

深拷贝 不仅复制对象属性的值,还复制属性本身。无论属性值是简单类型还是引用类型,它都会被复制。因此,如果复制的是引用类型的值,则原始对象和副本将指向不同的底层数据结构。

const obj1 = {
  name: '张三',
  age: 20,
  friends: ['李四', '王五']
};

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

console.log(obj2); // { name: '张三', age: 20, friends: ['李四', '王五'] }

obj2.name = '李四';
obj2.friends.push('赵六');

console.log(obj1); // { name: '张三', age: 20, friends: ['李四', '王五'] }

在这个示例中,obj2obj1 的深拷贝。当修改 obj2 的属性或属性值时,obj1 不会受到影响。这是因为深拷贝复制了对象本身以及其所有属性和属性值。

浅拷贝与深拷贝的选择

浅拷贝和深拷贝各有其优缺点。

浅拷贝的优点:

  • 速度快
  • 占用内存少

浅拷贝的缺点:

  • 不能复制引用类型的值
  • 复制引用类型的值时,原始对象和副本指向同一底层数据结构

深拷贝的优点:

  • 可以复制引用类型的值
  • 复制引用类型的值时,原始对象和副本指向不同的底层数据结构

深拷贝的缺点:

  • 速度慢
  • 占用内存多

在实际开发中,选择浅拷贝还是深拷贝应根据具体情况而定。

总结

浅拷贝和深拷贝是 JavaScript 中复制对象的重要技术,它们在复制过程和影响上有不同的特性。浅拷贝只复制属性值,而深拷贝则复制整个对象。在选择哪种方法时,应考虑具体情况的需要和权衡。熟练掌握浅拷贝和深拷贝有助于编写更高效、更健壮的 JavaScript 代码。

5 个常见问题解答

  1. 何时使用浅拷贝?

    • 当不需要复制引用类型的值时
    • 当需要快速复制对象时
    • 当内存使用是关键因素时
  2. 何时使用深拷贝?

    • 当需要复制引用类型的值时
    • 当需要避免修改原始对象时
    • 当需要创建完全独立的对象副本时
  3. 如何创建浅拷贝?

    • 使用 Object.assign() 方法
    • 使用扩展运算符 ...
  4. 如何创建深拷贝?

    • 使用 JSON.parse(JSON.stringify()) 方法
    • 使用循环和递归
  5. 浅拷贝和深拷贝有什么区别?

    • 浅拷贝只复制属性值,而深拷贝复制整个对象
    • 浅拷贝复制引用类型的值时,原始对象和副本指向同一底层数据结构,而深拷贝创建独立副本