JavaScript浅拷贝和深拷贝的区别

44 阅读2分钟

JavaScript浅拷贝和深拷贝的区别

在 JavaScript 中,浅拷贝深拷贝是两种不同的对象复制方式,主要区别在于对嵌套对象的处理。以下是它们的详细对比:

1. 浅拷贝(Shallow Copy)

  • 定义

    • 浅拷贝只复制对象的第一层属性,如果属性是引用类型(如对象、数组),则复制其引用,而不是实际的值。
  • 特点

    • 嵌套对象与原对象共享同一引用。

    • 修改嵌套对象会影响原对象。

  • 实现方式

  • 扩展运算符

const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
  • Object.assign
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = Object.assign({}, obj);
  • 数组的 sliceconcat
const arr = [1, 2, { a: 3 }];
const shallowCopy = arr.slice();

2. 深拷贝(Deep Copy)

  • 定义

    • 深拷贝会递归复制对象的所有层级,包括嵌套对象和数组,生成一个完全独立的新对象。
  • 特点

    • 嵌套对象与原对象不共享引用。

    • 修改嵌套对象不会影响原对象。

  • 实现方式

  • JSON.parse(JSON.stringify(obj))

const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
  • 局限性

  • 无法复制函数、undefinedSymbol 和循环引用。

  • 递归实现

function deepCopy(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }
  const copy = Array.isArray(obj) ? [] : {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key]);
    }
  }
  return copy;
}
const obj = { a: 1, b: { c: 2 } };
const deepCopy = deepCopy(obj);
  • 使用库函数

  • 使用 lodashcloneDeep 方法:

const _ = require('lodash');
const obj = { a: 1, b: { c: 2 } };
const deepCopy = _.cloneDeep(obj);

3. 示例对比

  • 浅拷贝
const obj = { a: 1, b: { c: 2 } };
const shallowCopy = { ...obj };
shallowCopy.b.c = 3;
console.log(obj.b.c); // 输出: 3(原对象被修改)
  • 深拷贝
const obj = { a: 1, b: { c: 2 } };
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.b.c = 3;
console.log(obj.b.c); // 输出: 2(原对象未被修改)

总结

特性浅拷贝深拷贝
复制层级只复制第一层属性递归复制所有层级
嵌套对象共享引用,修改会影响原对象独立引用,修改不会影响原对象
实现方式扩展运算符、Object.assign、sliceJSON.parse(JSON.stringify)、递归、库函数
适用场景简单对象复制复杂对象复制,需要完全独立的对象

根据具体需求选择合适的拷贝方式,可以避免意外的数据修改问题。

更多vue相关插件及后台管理模板可访问vue admin reference,代码详情请访问github