前端手写题之深拷贝

目录

WeakMap:

判断是否发生了循环引用 :

 深拷贝:


在解决深拷贝的时候要用到ES6新增的weakMap,和map一样,都是采取键值对存储的机制,其中的weak是指描述JS垃圾回收中的弱映射,也就是在weakmap中存储的值,并不会引用计数。

WeakMap:

API

初始化:

const wm = new WeakMap()

weakmap中的键,也就是key:value中的key必须是Object类型或是继承自Object类型,否则会抛出TypeError,初始化是全有或者全无的操作,例如:

const wm = new WeakMap([["key","value"]])//TypeError: Iterator value key is not an entry object
const stringKey = new String("key");
console.log(typeof stringKey);//Object
const wm1 = new WeakMap([[stringKey,"value"]])//注意要有两个[[]]
console.log(wm1.get(stringKey));//value

get()/set()/has():

const stringKey = new String("key");
console.log(typeof stringKey);//Object
const wm1 = new WeakMap([[stringKey,"value"]])//注意要有两个[[]]
console.log(wm1.get(stringKey));//value
const stringKey2 = new String('key2')
wm1.set(stringKey2,'value2')
console.log(wm1.get(stringKey2));//value2
console.log(wm1.has(stringKey2));//查询键名,true

Weak:

       Weak中的键处于弱引用,即引用计数不增加,但是键对应的值却不是弱引用,只要键存在,则值就存在,不会被当做垃圾回收。同时weakmap中的键值对因为在任何时候都可能会被销毁,所以不需要拥有迭代能力,也没有clear()方法来一次性的销毁。同时因为不可迭代,所以无法在不知道对象引用情况下从键去的值,所以即使访问到weakmap实例也无法知道其内容

console.log(wm1);//WeakMap { <items unknown> }

判断是否发生了循环引用 :

let a={},b={}
a.b = b
b.a = a
function isCall(obj,hash = new WeakMap()){
    if(obj == null || typeof obj !== 'object')return obj //若为基本数据类型、function、Date、正则,直接返回
     if(obj instanceof RegExp)return//typeof RegExp也为 object
    if(obj instanceof Date)return
     //判断是否为循环引用
    if(hash.get(obj)){
        console.log("发生了循环引用");
        return hash.get(obj)
    }
    //创建空的数组/对象
    let newobj = obj.constructor()
    hash.set(obj,newobj)
    //循环遍历
    for(let key in obj){
        //如果当前为obj自有属性
        if(obj.hasOwnProperty(key))isCall(obj[key],hash)
    }
    return 
}
isCall(a)//发生了循环引用

 深拷贝:

与以往的深拷贝由一些不同点:

1.利用WeakMap判断是否发生了循环引用

2.一般的深拷贝会对传进来的对象进行判断,看是对象还是数组:

const newData = Array.isArray(obj)?[]:{}

可以直接利用构造函数来new 一个空的数组或是对象

let cloneObj = new obj.constructor()

 3.hasOwnProperty()判断自有属性

完整代码:

function DeepClone(obj,hash = new WeakMap()){
    if(obj == null || typeof obj !== 'object')return obj //若为基本数据类型、function、Date、正则,直接返回
    if(obj instanceof RegExp)return new RegExp(obj) //typeof RegExp也为 object
    if(obj instanceof Date)return new Date(obj)//typeof Date也为 object
    //判断是否为循环引用
    if(hash.get(obj))return hash.get(obj)
    //创建空的数组/对象
    let cloneObj = new obj.constructor()
    hash.set(obj,cloneObj)
    //循环遍历
    for(let key in obj){
        //如果当前为obj自有属性
        if(obj.hasOwnProperty(key)){
            cloneObj[key] = DeepClone(obj[key],hash)
        }
    }
    return cloneObj
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值