zoukankan      html  css  js  c++  java
  • 递归实现深拷贝( 只要学过js递归,看不懂找我包会 )

    要用递归实现深拷贝,首先说说什么是深拷贝和浅拷贝

    浅拷贝:一个值赋给另一个值,当原先的值不改变地址的情况下改变数据,另一个值跟着变
    深拷贝:一个值赋给另一个值,当原先的值不改变地址的情况下改变数据,另一个值不变
     
    注意 : 强调一点,原先的值不改变地址的情况下改变数据,如果是改了地址的改变,那将用另一个值的改变与否判断深拷贝浅拷贝毫无意义
     
    // 举一个简单的例子---以下的obj,obj2可以看做是这里的obj,obj2
    
    var obj = {
        name : 'zs',  
        age : 18  
    }
    // 浅拷贝
    var obj2 = obj;
    obj.name = 'ls';
    console.log(obj2) // { name : 'ls' , age : 18  }

    这是浅拷贝,单单就是把obj的地址给了obj2,obj改了,obj2也要改。再来说说这obj改了,这里面有点不同。要么 obj改了属性(数组就是改了元素),要么干脆obj指向另一个地址,例如:obj = 1;针对第一种就是深浅拷贝可以作为判断依据的,根据改了之后obj2改不改就可以看出深拷贝(不改)还是浅拷贝(改了)。第二种不管深浅拷贝的因为obj的地址变了,obj再怎么改都不会影响obj2,因此obj2肯定不会变,深浅拷贝看不出来的

    var obj = {
        name : 'zs',  
        age : 18  
    }
    var obj2 = obj;
    // obj 自己地址都变了,再怎么折腾影响不了obj2了
    obj = 1;
    console.log(obj2) // { name : 'zs' , age : 18  }

    //  以上 obj可以看做第一个对象(数组) ,obj2 可以看做第二个对象(数组) ,为什么不说函数呢? 因为函数本身办法改内容,声明的时候已经确定好函数体了,你还能有神通在不改变声明函数的函数体前提下,后续添加函数体语句?如果可以,请教教我,说真的!

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    以下重点说说深拷贝 : 说白了深拷贝的目的就是不想让obj来影响obj2,有点过河拆桥的意思,把好处或爱情给了另一个人,另一个人却不想让你打扰她(说多了是泪)

    针对以下三种常见情况提供三种方式进行深拷贝 : 

    很纯的对象 : 属性值没有数组、对象的   var obj2 = Object.assgin({ }, obj)

    没有方法的对象 (没有方法在内,可以有数组和对象充当属性值) : var obj2 = JSON.parse(JSON.stringify(obj)) 

            var u = {
                o : {'name' : 'zs'},
                i : 5
            }
            var v = JSON.parse(JSON.stringify(u))
            u.o.name = 'ls';
            console.log(u,v);  // v的o属性中的name还是'zs'

    ③ 递归( 通用,从底层的角度 ) 基本思想 : 判断obj 是基本类型就简单赋值,对象(数组)的话 ,创建一个空[ ](obj是对象)或空{ }(obj是对象),再判断obj的属性有没有对象(数组),有递归调用,没有简单赋值,直到全部赋值完毕,返回赋值后的new_obj , 看不懂没关系下面代码有注释,绝对可以看懂

    var obj = {
                arr1 : [1,2,3],
                fn: function(){
                    console.log('我是一个方法')
                },
                a : '我是普通属性'
            }
            
            // 现在我要把obj字面量创建里的属性深拷贝( 属性值是引用类型也要深拷贝 )
            function deepClone(obj){
                // 根据类型制造一个新的数组或对象 => 指向一个新的空间
                    // 由于数组的typeof也是'object',所以用Array.isArray(obj)
                var new_obj = Array.isArray(obj) ? [] : {};
                // 首先判断obj的类型
                    // 普通类型
                if( typeof obj != 'object' ){
                    // 这里不能直接返回obj,不然就是浅拷贝的性质
                    return  new_obj = obj
                }
                    //引用类型
                        //数组
                if(obj instanceof Array ){
                    for(i = 0; i < obj.length; i++ ){
                        new_obj[i] = obj[i];
                        if(typeof new_obj[i] == 'object'){
                            deepClone(new_obj[i])
                        }
                    }
                }else{ //对象
                    for (let key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            // 对象中的数组和对象
                            if (typeof obj[key] == 'object') {
                                new_obj[key] = deepClone(obj[key]); 
                            }else{//对象中没有引用类型
                                new_obj[key] = obj[key]
                            }  
                        }
                    }
                }
                return new_obj;
            }
            var deepClone = deepClone(obj);
            console.log(deepClone);
            // 测试是不是深拷贝
            obj.fn = '我改变了方法属性';
            console.log(obj); //{arr1: Array(3), fn: ƒ, a: "我是普通属性", c: "我新增了一个属性"}
            console.log(deepClone); // 还是 {arr1: Array(3), fn: ƒ, a: "我是普通属性"}

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    本文原创,仅供学习使用

  • 相关阅读:
    python 字符串前面加u,r,b的含义
    文本检测: CTPN
    ocr 识别 github 源码
    python 中写hive 脚本
    Win10 环境安装tesseract-ocr 4.00并配置环境变量
    OCR 识别原理
    pandas set_index和reset_index的用法
    整理 pandas 常用函数
    js es6 map 与 原生对象区别
    js 暂时性死区
  • 原文地址:https://www.cnblogs.com/wchjdnh/p/10796422.html
Copyright © 2011-2022 走看看