JS深拷贝的实现

2019-07-17  本文已影响0人  y先生_f18f

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

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

  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))
上一篇下一篇

猜你喜欢

热点阅读