JS深拷贝和浅拷贝,实现深拷贝的工具方法

什么是深拷贝和浅拷贝?

浅拷贝:B复制了A,A发生变化B也跟着发生变化
深拷贝:B复制了A,A发生变化B不会跟着变化

为什么拷贝分深拷贝和浅拷贝?

基本类型和引用类型在内存中存储是有区别的,基本类型的数据是直接存储的它的值在内存栈中,而引用类型的数据存储的是它的引用地址在内存栈中,这个引用地址指向的在堆中的数据才是这个引用类型的正确数据。
一般引用类型的数据的复制只是复制它的引用地址,复制引用地址的行为就是浅拷贝。
所以引用类型的数据才存在深拷贝和浅拷贝,如对象和数组
在这里插入图片描述

1、如何实现深拷贝

1.1、通过JSON.parse(JSON.stringify)序列化

这是一个比较简便的方法,写法简单,如果要拷贝的对象中都是一些基本数据类型的数据可以使用这个方法

let origin = {name: '张三', age: 24}
let result = JSON.parse(JSON.stringify(origin))

但是存在一些弊端:

  • 如果拷贝对象里有时间对象,时间将只是字符串的形式,而不是对象的形式
  • 如果拷贝对象里有RegExp、Error对象,那得到的结果是空对象
  • 如果拷贝对象里有函数、undefined,得到的结果会把函数或undefined丢失
  • 如果拷贝对象里有NaN、Infinity,结果会变成null
  • 只能拷贝对象的可枚举的自有属性,如果拷贝对象中的对象是有由构造函数生成的,会丢弃对象的constructor

1.2、通过自定义深拷贝方法

如果要深拷贝的内容中有一些像时间对象正则对象Error对象函数undefinedNaNInfinity不可枚举的自由属性对象的constructor,就需要用下面这个方法了,不然会出现1.1中说的弊端这些问题

function deepClone(original, cache = new WeakMap()) {
    if (typeof original !== 'object') return original
    if (original === null) return original
    if (cache.get(original)) return cache.get(original) // 防止循环引用进入死循环
    if (original instanceof Date) return new Date(original)
    if (original instanceof RegExp) return new RegExp(original)

    // 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数
    let cloneObj = new original.constructor()
    cache.set(original, cloneObj) // 缓存拷贝的对象,用于处理循环引用的情况
    for (let key in original) {
        if (original.hasOwnProperty(key)) {
            cloneObj[key] = util.deepClone(original[key], cache) // 递归拷贝
        }
    }
    return cloneObj
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值