js深拷贝(递归实现)【完美版解决包装对象Number,String , Boolean,Date,RegExp】

const deepClone =(initalObj) =>
    {
        if (typeof initalObj !== 'object') {//如果是基本类型直接返回值
            return initalObj
        }
        const obj = Array.isArray(initalObj)?[]:{};//可能是对象或者数组
        for (const key in initalObj) {
            if (typeof initalObj[key] === 'object') {//对于对象元素,deepclone
                //递归返回新的对象
                obj[key] = deepClone(initalObj[key]);
            } else if (typeof initalObj[key] === 'function') {//对于函数,用bind拷贝
                //返回新函数
                obj[key] = initalObj[key].bind(obj);
            } else {
                //基本类型直接返回
                obj[key] = initalObj[key];
            }
        }
        return obj;
    }

改进:

通过递归可以简单实现对象的深度克隆,但是这种方法不管是ES6还是ES5实现,都有同样的缺陷,就是只能实现特定的object的深度复制(比如数组和函数),不能实现包装对象Number,String , Boolean,以及Date对象,RegExp对象的复制。
下面是完美版的深拷贝
参考自:https://blog.csdn.net/liwusen/article/details/78759373

function istype(obj,type){//判断包装类型的原型
    return Object.prototype.toString.call(obj).indexOf(type)!=-1
}
const deepClone =(initalObj) =>
    {
        if (typeof initalObj !== 'object') {//如果是基本类型直接返回值
            return initalObj
        }
        if(istype(initalObj,'String')||istype(initalObj,'Number')||istype(initalObj,'Boolean'))
            return initalObj.valueOf();
        if(istype(initalObj,'Date'))
            return new Date(initalObj.valueOf());
        if(istype(initalObj,'RegExp')){
            let pattern = initalObj.valueOf();
            let flags = '';
            flags += pattern.global ? 'g' : '';
            flags += pattern.ignoreCase ? 'i' : '';
            flags += pattern.multiline ? 'm' : '';
            return new RegExp(pattern, flags);
        }
        const obj = Array.isArray(initalObj)?[]:{};//可能是对象或者数组
        for (const key in initalObj) {
            if (typeof initalObj[key] === 'object') {//对于对象元素,deepclone
                //递归返回新的对象
                obj[key] = deepClone(initalObj[key]);
            } else if (typeof initalObj[key] === 'function') {//对于函数,用bind拷贝
                //返回新函数
                obj[key] = initalObj[key].bind(obj);
            } else {
                //基本类型直接返回
                obj[key] = initalObj[key];
            }
        }
        return obj;
    }

测试

const obj = {
    a: 1,
    b: {b1:[],b2:[]},
    c: { d: {}, g: () => {} },
    e: () => {},
    f: function() {}
}
const newObj = deepClone(obj);
console.log(newObj.a === obj.a);
console.log(newObj.b === obj.b);
console.log(newObj.c === obj.c);
console.log(newObj.c.d === obj.c.d);
console.log(newObj.c.g === obj.c.g);
console.log(newObj.e === obj.e);
console.log(newObj.f === obj.f);
const o2=deepClone([0,obj,[1]])
console.log(o2);
var str=new String("hello");
console.log(Object.prototype.toString.call(str))
console.log(deepClone(str));
console.log(Object.prototype.toString.call(new Number()))
console.log(deepClone(new Number(100)));
console.log(Object.prototype.toString.call(new Date()))
console.log(deepClone(new Date()));
console.log(Object.prototype.toString.call(new RegExp('/111/')))
console.log(deepClone(new RegExp('/111/')));

js深拷贝(递归实现)【完美版解决包装对象Number,String , Boolean,Date,RegExp】_第1张图片

你可能感兴趣的:(前端,前端面试,js,深拷贝)