前端实现深浅拷贝

目录

概念

实例

1.浅拷贝的实现方式

使用 Object.assign() 方法进行浅拷贝:

使用扩展运算符(...)进行浅拷贝:

2.深拷贝的实现方式:

使用 JSON.parse(JSON.stringify()) 进行深拷贝:

使用递归进行深拷贝:

小结

概念

在前端开发中,我们经常会遇到对数据进行拷贝的需求。拷贝可以分为深拷贝和浅拷贝两种方式。

浅拷贝指的是创建一个新的对象,新对象的引用类型属性仍然指向原对象的引用。也就是说,只拷贝了对象的引用,而没有拷贝对象本身。

深拷贝则是将原对象完全复制一份,包括对象的属性和引用类型的属性。也就是说,拷贝了对象本身和对象的引用。

实例

1.浅拷贝的实现方式

使用 Object.assign() 方法进行浅拷贝:
let obj1 = { name: 'Tom', age: 18 };
let obj2 = Object.assign({}, obj1);
console.log(obj2); // { name: 'Tom', age: 18 }
 

在这个例子中,通过 Object.assign() 方法将 obj1 对象的属性拷贝到了 obj2 对象中。这种方式只会拷贝对象的属性,而不会拷贝对象的引用。

使用扩展运算符(...)进行浅拷贝:
let obj1 = { name: 'Tom', age: 18 };
let obj2 = { ...obj1 };
console.log(obj2); // { name: 'Tom', age: 18 }
 

扩展运算符(...)可以将一个对象的属性解构到另一个对象中。这种方式和 Object.assign() 方法的效果是一样的。

2.深拷贝的实现方式:

使用 JSON.parse(JSON.stringify()) 进行深拷贝:
let obj1 = { name: 'Tom', age: 18, hobbies: ['reading', 'swimming'] };
let obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2); // { name: 'Tom', age: 18, hobbies: ['reading', 'swimming'] }
 

JSON.stringify() 方法将对象转换为 JSON 字符串,然后再使用 JSON.parse() 方法将 JSON 字符串转换回对象。由于 JSON 格式不支持函数和 undefined,所以这种方式无法拷贝对象的函数和 undefined 属性。

使用递归进行深拷贝:
function deepClone(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }
  let result = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      result[key] = deepClone(obj[key]);
    }
  }
  return result;
}

let obj1 = { name: 'Tom', age: 18, hobbies: ['reading', 'swimming'] };
let obj2 = deepClone(obj1);
console.log(obj2); // { name: 'Tom', age: 18, hobbies: ['reading', 'swimming'] }
 

这种方式通过递归的方式,遍历对象的属性,将对象的属性和引用类型的属性递归复制到新的对象中,实现了深拷贝。

注:这里使用了Object.prototype.hasOwnProperty.call(obj, key) 是因为直接使用obj.hasOwnProperty(key)导致ESLint报错。ESLint 不允许从目标对象调用 Object 原型方法。

报错如下

小结

浅拷贝只是拷贝了对象的引用,而不拷贝对象本身和对象的引用类型属性。深拷贝则是将对象完全复制一份,包括对象的属性和引用类型属性。

对于浅拷贝,可以使用 Object.assign() 方法或扩展运算符(...)进行实现;对于深拷贝,可以使用 JSON.parse(JSON.stringify()) 方法或递归进行实现。

需要注意的是,使用 JSON.parse(JSON.stringify()) 方法进行深拷贝时,无法拷贝对象的函数和 undefined 属性。在使用递归进行深拷贝时,需要处理循环引用的情况,否则会出现栈溢出的错误。

  • 34
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值