• JavaScript之复杂对象的深拷贝(完全深拷贝)


    由于网上很多的深拷贝大都有如下问题:

      1.灵活性。不能应对复杂对象(复杂对象是指:单一数组对象、多数组对象、多非数组对象、单一对象组合形成的复杂对象)的灵活拷贝

      2.不变性。即 拷贝的对象与原对象的结构发生了变化(尤其是:将数组对象经过拷贝后人为变成了非数组对象),破坏了结构并不是深拷贝的初衷。

    依据上述问题,花费了三个小时左右的思考和调试,得以解决。

    声明:如需读者记录笔记或者摘要时,请声明引用出处,以尊重劳动成果~,谢谢,当然也可以向博主提出意见~

    //判断是否为字符串
    //返回类型:
    //{baseType:typeof(arg),numberType:'int','float',-1}
    function numberType(arg){
        var baseType;
        var numberType;
        var regx_int =  /^[0-9]*[1-9][0-9]*$/;
        if(!isNaN(arg)){//JavaScript中,属于数值的有:数值型字符串和真实数值       
            baseType = typeof(arg);//输出:string or number
            if(regx_int.test(arg)){//整数
                numberType = "int";
            } else {
                numberType = "float";
            }
        } else {
            baseType = typeof(arg);
            numberType = -1;
        }
    
        return {
            "arg":arg,
            "baseType": baseType,//注意:typeof(stringNumber):string
            "numberType": numberType
        }
    }
    /*
        console.log(numberType("23"));  //{arg: "23", baseType: "string", numberType: "int"}
        console.log(numberType("23.0"));//{arg: "23.0", baseType: "string", numberType: "float"}
        console.log(numberType("23a")); //{arg: "23a", baseType: "string", numberType: -1}
        console.log(numberType(23));    //{arg: 23, baseType: "number", numberType: "int"}
        console.log(numberType(23.0));  //{arg: 23, baseType: "number", numberType: "int"}
     */
    
    //url:[js中的深拷贝和浅拷贝](http://www.jianshu.com/p/70dc5b968767)
    //依赖:recursion(obj, data)
    function cloneDeep(obj){
        
        if( typeof obj !== 'object' || Object.keys(obj).length === 0 ){
            return obj
        }
    
        let resultData;
        if( typeof obj == 'object' && (obj instanceof Array))
            resultData = [];
        else {
            resultData = {};
        }
    
        return recursion(obj, resultData)
    }
    
    //url:[js中的深拷贝和浅拷贝](http://www.jianshu.com/p/70dc5b968767)
    //被依赖:cloneDeep(obj)
    //依赖:numberType(num)
    function recursion(obj, data = {}){
        // console.log('[recursion] data:"' + data + '"; execute: obj:', obj);
        for(key in obj){//注意:使用for Each遍历时,会将数值转型为string类型
                // console.log('cur:' + obj + '[' + key + ']:', obj[key]);
                if( (typeof obj[key] == 'object') && (obj[key] instanceof Array) && Object.keys(obj[key].length > 0 )){
                    // console.log('key[' + key + '] is Array:', obj[key]);
                    var array = new Array();
                    for(var i = 0, size = obj[key].length; i < size; i++){
                        (function(index){
                            array.push((obj[key][index]));
                        })(i)
                    }
                    data[key] = array;
                    // console.log('data[key] data:', data[key]);
                } 
                else if( (typeof obj[key] == 'object') && (!(obj[key] instanceof Array)) && Object.keys(obj[key].length > 0 )){
                    // console.log('key[' + key + '] is Object but not Array:', obj[key]);
                    data[key] = recursion(obj[key], {});
                    // console.log('data[key] data:', data[key]);
                } else {
                    // console.log('key[', key, '] is not object, ','key is ',typeof(key), ', obj[key]:' + obj[key] + ' is ',typeof(key));
                    var nType = numberType(key);
                    if(nType.baseType == "string"){//由于forEach的原因,所有的key都是字符串或者对象
                        // console.log('* nType:', nType);
                        // console.log('* data.push(obj[key]):', data.push(obj[key]));
                        // console.log('* obj[key] instanceof Array:', obj[key] instanceof Array);
                        if(nType.numberType == -1){//如果是真实的字符串或者非数值类型(即 非数值字符串或 真实数值类型),则说明是对象的一个属性
                            data[key] = obj[key];
                        } else {//反之:该属性为真实数值类型,说明key作为数组的(下标)键值
                            data.push(obj[key]);
                            // console.log('test obj[key]:', obj[key]);
                        }
                    }
                    data[key] = obj[key];//实际上,此处无过多实际意义和用意
                    // console.log('data[ ' + key +' ] data:', data[key]);
                }
                // console.log('___________________________________[data]_________________________:', data);//test:遍历一次时,查看当前拷贝对象data的状态
            }
        return data;
    }
    

    使用方式与测试:

    var courses = [{"name":"面向对象分析与设计","week_index":1,"course_index":[2,3],"week_start":5,"week_end":16,"teacher":"王敏","location":"6B-108多媒体286座(2017-2018-2)-150905319-0120030135-1"}];
    // typeof(courses);
    newCourses = recursion(courses, []);
     
    studentCourses = cloneDeep(student); 
    
    console.log(studentCourses,newCourses); 
    

      

    效果:

  • 相关阅读:
    UnxUtils让windows下的dos命令变为linux下的命令
    Python多线程&进程
    Web前端工程师-优秀简历汇总
    最详细的Vuex教程
    Vue2.0 探索之路——生命周期和钩子函数的一些理解
    理解 $nextTick 的作用
    使用git rebase合并多次commit
    vim 退出命令(保存、放弃保存)
    Vue获取DOM元素样式 && 样式更改
    Vue Router的配置
  • 原文地址:https://www.cnblogs.com/johnnyzen/p/7992167.html
Copyright © 2020-2023  润新知