• js中的拷贝问题以及深拷贝中因为循环引用造成的死循环问题


    拷贝分为深拷贝和浅拷贝,通俗来讲就是B复制了A的内容,当A进行了修改以后,看B是否变化,如果变化了就是浅拷贝,如果没有变化就是深拷贝。

    浅拷贝:

      var a = {
            key1:"111"
        }
        function copy(p){
    //        console.log(p)
            var c = {};
            for(var i in p){
                c[i] = p[i];
    //            console.log(i)  //  key1
            }
            return c;
        }
    //    copy(a);
        a.key2 = ["you","me"];
        var b = copy(a);
        b.key3 = "ours";
        console.log(a.key3);   //  undefined
        console.log(b.key3)   //  ours
    //    console.log(b)   //  {key1:"111",key2:["you","me"]}
        b.key2.push("us")
        console.log(b.key2);   //  ["you", "me", "us"]
        console.log(a.key2);   //  ["you", "me", "us"]
    

      

    深拷贝:

    第一种:递归深拷贝
        function deepClone(obj){
    //      定义一个变量 并判断是数组还是对象
            var objClone = Array.isArray(obj) ? [] : {};
            if(obj && typeof obj === "object" && obj != null){ 
     // 判断obj存在并且是对象类型的时候 因为null也是object类型,所以要单独做判断
                for(var key in obj){  //  循环对象类型的obj
                    if(obj.hasOwnProperty(key)){  //  判断obj中是否存在key属性
                        if(obj[key] && typeof obj[key] === "object"){  //  判断如果obj[key]存在并且obj[key]是对象类型的时候应该深拷贝,即在堆内存中开辟新的内存
                            objClone[key] = deepClone(obj[key]);
                        }else{  //  否则就是浅复制
                            objClone[key] = obj[key];
                        }
                    }
                }
            }
            return objClone;
        }
        var a = {
            name:"key1",
            eat:[
                "苹果",
                "香蕉"
            ]
        }
        b = deepClone(a);
    //    console.log(b);
        a.eat = [
            "苹果",
            "香蕉",
            "橙子"
        ];
        console.log(a);  //  {name:"key1",eat:["苹果","香蕉","橙子"]}
        console.log(b)   //  {name:"key1",eat:["苹果","香蕉"]}
    
    递归运行效率低,次数过多的话容易造成栈溢出。
    

      

    第二种:JSON的parse和stringify方法实现深复制
        function deepClone(obj){
    //        console.log(obj);
    //        console.log(typeof obj);
            var _obj = JSON.stringify(obj);  //  对象转成字符串
    //        console.log(_obj);
    //        console.log(typeof _obj);
            var objClone = JSON.parse(_obj); //  字符串转成对象
    //        console.log(objClone);
    //        console.log(typeof objClone);
            return objClone;
        }
        var a = [0,1,[2,3],4];
        b = deepClone(a)
        a[0] = 6;
        a[2][0] = 7;
        console.log(a);   //  [6,1,[7,3],4]
        console.log(b);   //  [0,1,[2,3],4]
    

      

    第三种:jq的$.extend 深拷贝
        var a = [0,1,[2,3],4];
        b = $.extend(true,[],a);
        a[0] = 1;
        a[2][0] = 7;
        console.log(a);   //  [1,1,[7,3],4];
        console.log(b);   //  [0,1,[2,3],4];
    
    $.extend参数:
    第一个参数是布尔值,是否深复制
    第二个参数是目标对象,其他对象的成员属性将被附加到该对象上
    第三个及以后的参数是被合并的对象
    

      解决深拷贝中因为循环引用造成的死循环问题(使用数组方法)

    function find(arr,item){
            for(var i=0; i<arr.length; i++){
                if(arr[i].source === item){
                    return arr[i]
                }
            }
            return null;
        }
        function isObject(obj) {
            return typeof obj === 'object' && obj != null;
        }
    
        function deepClone(source,uniqueList){
            if(!isObject(source)) return source;
    
            if(!uniqueList) uniqueList = [];    //   初始化数据
    
            var target = Array.isArray(source) ? [] : {};
    
            var uniqueData = find(uniqueList,source);
            if(uniqueData) return uniqueData.target;
    
    
            uniqueList.push({
                source:source,
                target:target
            });
    
            for(var key in source){
                if(Object.prototype.hasOwnProperty.call(source,key)){
                    if(isObject(source[key])){
                        target[key] = deepClone(source[key], uniqueList)      //   传入数组
                    }else{
                        target[key] = source[key];
                    }
                }
            }
            return target;
        }
        var a = {
            name:"key1",
            eat:[
                "苹果",
                "香蕉"
            ]
        }
        b = deepClone(a);
    //    console.log(b);
        a.eat[2] = "桃";
        a.d = a;
        console.log(a);
        console.log(b);
    

      

  • 相关阅读:
    第四十一节 jQuery之bootstrap文档
    第四十节 jQuery之bootstrap简介
    Redis 如何实现查询附近的距离
    线上日志快速定位-grep
    Java字符串操作工具类
    JAVA批量插入数据操作+事务提交
    java开发需求中技术常见名称
    MySQL Binlog--MIXED模式下数据更新
    MySQL Replication--修改主键为NULL导致的异常
    MySQL Replication--复制异常1
  • 原文地址:https://www.cnblogs.com/ly-qingqiu/p/10881801.html
Copyright © 2020-2023  润新知