js的拷贝

153 阅读1分钟

JSON

源码:

JSON.parse(JSON.stringify())

缺点:

  • 1、对象的循环引用的拷贝直接报错,不能拷贝
  • 2、对象方法直接抛弃,拷贝函数返回undefined 详见链接:www.jianshu.com/p/b084dfaad…

深度优先拷贝

源码:

function DFdeepClone(obj, originObjs = [], cloneObjs = []){
    let _obj = Object.prototype.toString.call(obj) === '[object Array]'  ? [] : {};
    if (Object.prototype.toString.call(obj) === '[object Object]'
     || Object.prototype.toString.call(obj) ==='[object Array]'){
        let index = originObjs.indexOf(obj);
        if (~index){
            _obj = cloneObjs[index];
        } else {
            originObjs.push(obj);
            cloneObjs.push(_obj);
            for(let item in obj){
                _obj[item] = DFdeepClone(obj[item], originObjs, cloneObjs);
            }
        }
    } else if (Object.prototype.toString.call(obj) === '[object Function]' ) {
        _obj = eval("("+ obj.toString() +")");
    } else {
        _obj = obj;
    }
    return _obj;
}

优点

  • 1、相对于JSON序列化,能拷贝方法,能拷贝循环引用数据

缺点

  • 1、数据太长会栈溢出

广度优先拷贝

源码:

function BFdeepClone(obj){
    // 返回的拷贝对象
    let copyObj = {};

    // 循环数据的队列,用来检测是否有循环引用数据
    let visitedOriginQuene = [];
    let visitedCopyQuene = [];

    // 广度优先必须的遍历序列
    let originQuene = [obj];
    let copyQuene = [copyObj];

    while (originQuene.length !== 0) {
        let itemObj = originQuene.shift();
        let _copyObj = copyQuene.shift();
        let itemType = Object.prototype.toString.call(itemObj);
        visitedOriginQuene.push(itemObj);
        visitedCopyQuene.push(_copyObj);

        if (itemType === '[object Object]' 
        || itemType === '[object Array]'){
            for (let objKey in itemObj) {
                let objVal = itemObj[objKey];
                let valType = Object.prototype.toString.call(objVal);
                if(valType === '[object Object]' 
                || valType === '[object Array]'){
                    let index = visitedOriginQuene.indexOf(objVal);
                    if (index === -1){
                        _copyObj[objKey] = valType === '[object Array]'?[]:{};
                        originQuene.push(itemObj[objKey]);
                        copyQuene.push(_copyObj[objKey]);
                    } else {
                        _copyObj[objKey] = visitedCopyQuene[index];
                    }
                } else if (valType === '[object Function]') {
                    _copyObj[objKey] = eval("("+objVal.toString()+")");
                } else {
                    _copyObj[objKey] = objVal;
                }
            }
        } else if (itemType === '[object Function]') {
            copyObj = eval("("+itemObj.toString()+")");
        } else {
            copyObj = itemObj;
        }
    }
    return copyObj;
}

优点

  • 1、能拷贝方法,能拷贝循环引用数据

缺点

  • 1、牺牲了较大的时间复杂度和空间复杂度

结语

方法拷贝进控制台直接运行,有问题,还请斧正!