美文网首页
JS深拷贝的实现

JS深拷贝的实现

作者: y先生_f18f | 来源:发表于2019-07-17 22:49 被阅读0次

    在面试中经常问到深拷贝的实现,但由于在项目中都是用网上现成的或者依赖各种函数库完成。偶尔在回答的时候就脑袋短路了,现在有时间了就简单整理了一下。

    先说一下自己用过的一些方法

    1. 通过 JSON 对象实现深拷贝
    //通过js的内置对象JSON来进行数组对象的深拷贝
    function deepClone(obj) {
        var _obj = JSON.stringify(obj),
        objClone = JSON.parse(_obj);
        return objClone;
    }
    

    缺陷:它会抛弃对象的constructor,深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object;这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON;

    1. lodash函数库实现深拷贝
    lodash是一个很优秀的函数库,提供了 lodash.cloneDeep()实现深拷贝
    
    1. Object.assign()拷贝
    当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝
    

    上面这几种方法都能简单的实现深拷贝,但是各有各的特点,也有各方面的缺点。所以就有了下面作者自己的实现方式。

    function deepClone(value,hash = new WeakMap){  // WeakMap弱引用,不要用map
        if(value == null){
            return null;
        }
        if(value instanceof RegExp){
            return new RegExp(value);
        }
        if(value instanceof Date){
            return new Date(value);
        }
        //函数不需要拷贝
        if(typeof value != 'object') return value;
    
        let obj = new value.constructor;  //判断是对象还是数组 并且new
    
        if(hash.get(value)){  //如果这个对象拷贝过了 就返回那个拷贝的结果就可以了
            return hash.get(value);
        }
    
        hash.set(value,obj);   //如果这个对象没有拷贝过 就添加到WeakMap里面
    
        for (let key in value) {  // in 会遍历当前对象上面的属性和__proto__指代的属性
            if (value.hasOwnProperty(key)) {
                // 如果值还有可能是对象 就利用递归继续拷贝
                obj[key] = deepClone(value[key],hash)
            }
        }
        return obj;
        
        //区分对象和数组 Object.prototype.tostring.call
    }
    
    let o = {name: '123'};
    console.log(deepClone(o))
    

    相关文章

      网友评论

          本文标题:JS深拷贝的实现

          本文链接:https://www.haomeiwen.com/subject/idjhlctx.html