js 深拷贝 浅拷贝 详解

在JavaScript中,深拷贝和浅拷贝是两种常见的数据拷贝方式,它们用于在创建变量副本时决定如何复制对象和数组。深拷贝会创建一个完全独立的副本,而浅拷贝只是创建原对象的引用副本。

浅拷贝: 浅拷贝意味着只复制对象或数组的引用,新对象和原对象引用的是同一个存储空间。当修改其中一个对象时,另一个对象也会受到影响。

深拷贝: 深拷贝会递归地复制对象或数组及其所有嵌套的对象或数组,创建一个完全相同的副本,而不是引用原对象的存储空间。

下面是几种常见的深拷贝和浅拷贝的方法:

  1. 浅拷贝方法:

    • 使用Object.assign():这个方法可以将多个源对象的属性复制到目标对象中,返回目标对象。注意,它只会复制对象的一层属性,如果属性的值是对象或数组,则复制的是它们的引用。
    • 使用扩展运算符(...):通过扩展运算符可以将一个对象或数组的内容展开,创建一个新的对象或数组。同样,它只复制对象或数组的一层内容。
    • 使用Array.prototype.slice():对于数组,可以使用slice()方法创建一个浅拷贝。但它只适用于数组,对于对象无效。
  2. 深拷贝方法:

    • 使用JSON.parse()和JSON.stringify():利用JSON.stringify()将对象转为JSON字符串,再用JSON.parse()将JSON字符串转回对象。这个方法可以实现简单的深拷贝,但它有一些限制,比如无法处理函数、undefined和循环引用等。
    • 使用递归:递归地遍历对象或数组,对每个属性进行复制。当属性的值仍然是对象或数组时,递归地执行复制操作。这种方法可以实现完全深拷贝,但需要注意处理循环引用的情况。

下面是一个使用递归进行深拷贝的示例:

function deepCopy(obj, map = new WeakMap()) {
  // 如果是基本数据类型或null/undefined,则直接返回
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  // 处理特殊类型
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
  
  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }
  
  // 处理循环引用的情况
  if (map.has(obj)) {
    return map.get(obj);
  }
  
  let copy;
  
  // 创建一个新的对象或数组
  if (Array.isArray(obj)) {
    copy = [];
  } else {
    copy = {};
  }
  
  // 将新对象或数组放入map中,用于处理循环引用的情况
  map.set(obj, copy);
  
  // 遍历对象的属性或数组的元素,递归地进行深拷贝
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = deepCopy(obj[key], map);
    }
  }
  
  return copy;
}

使用方法如下:

const obj = {
  a: 1,
  b: [1, 2, 3],
  c: {
    d: 4,
    e: [5, 6]
  }
};

const copy = deepCopy(obj);

console.log(copy); // {a: 1, b: [1, 2, 3], c: {d: 4, e: [5, 6]}}
console.log(copy === obj); // false

copy.a = 2;
copy.b.push(4);
copy.c.e.push(7);

console.log(obj); // {a: 1, b: [1, 2, 3], c: {d: 4, e: [5, 6]}}
console.log(copy); // {a: 2, b: [1, 2, 3, 4], c: {d: 4, e: [5, 6, 7]}}

总结:

浅拷贝只复制对象的引用,而深拷贝复制对象及其所有嵌套的对象或数组。在实现深拷贝时,可以使用递归或其他方法。选择合适的拷贝方式取决于你的需求和数据结构的复杂度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值