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/')));

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章