zoukankan      html  css  js  c++  java
  • js中的深拷贝和浅拷贝2

    所谓 深浅拷贝
    对于仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响,为 浅拷贝
    而如果是在堆中重新分配内存,拥有不同的地址,但是值是一样的,复制后的对象与原来的对象是完全隔离,互不影响,为 深拷贝
     
    深浅拷贝 的主要区别就是:复制的是引用(地址)还是复制的是实例。
     1 //浅复制
     2 function shallowCopy(src){
     3     var dst = {};
     4     for(var key in src){
     5         if(src.hasOwnProperty(key)){
     6             dst[key] = src[key];
     7         }
     8     }
     9     return dst;
    10 }
    11 
    12 var obj = {
    13     a : 1,
    14     arr : [2,3]
    15 };
    16 var shallowObj = shallowCopy(obj);
    17 console.log(obj === shallowObj);   //false
    18 shallowObj.arr[1] = 5;
    19 console.log(obj.arr[1]);   // = 5
    20 console.log(obj);         //{ a: 1, arr: [ 2, 5 ] }
    21 console.log(shallowObj);  //{ a: 1, arr: [ 2, 5 ] }
    //利用 递归 来实现深复制,对属性中所有引用类型的值,遍历到是基本类型的值为止。
    function deepCopy(src){
        if(!src && typeof src !== 'object'){
            return;
        }
        var dst = src.constructor  === Array ? []:{};
        for(var key in src){
            if(src.hasOwnProperty(key)){
                if(src[key] && typeof src[key] === 'object'){
                    dst[key] = src[key].constructor === Array ? []:{};
                    dst[key] = deepCopy(src[key]);   //递归
                }else{
                    dst[key] = src[key];
                }
            }
        }
        return dst;
    }
    
    
    var a = {
        name:"jack",
        age:20
    };
    var b = deepCopy(a);
    console.log(a === b);   //false
    a.age = 30;
    console.log(a);     //{ name: 'jack', age: 30 }
    console.log(b);     //{ name: 'jack', age: 20 }

     深拷贝浅拷贝问题探究:

    1. Array 的 slice 和 concat 方法

    两者都会返回一个新的数组实例。

    //slice
    var a = [1,2,3];
    var b = a.slice(); //slice
        console.log(b === a);
    a[0] = 4;
        console.log(a); //[ 4, 2, 3 ]
        console.log(b); //[ 1, 2, 3 ]
    
    //concat
    var a = [1,2,3];
    var b = a.concat();  //concat
        console.log(b === a);
    a[0] = 4;
        console.log(a);  //[ 4, 2, 3 ]
        console.log(b);  //[ 1, 2, 3 ]

    看起来很像深拷贝,但实际上不是!!!

    //slice
    var a = [[1,2,3],4,5];
    var b = a.slice();
        console.log(a === b); //false
    a[0][0] = 6;
        console.log(a);   //[ [ 6, 2, 3 ], 4, 5 ]
        console.log(b);   //[ [ 6, 2, 3 ], 4, 5 ]
    
    //concat
    var a = [[1,2,3],4,5];
    var b = a.concat();  //concat
        console.log(b === a); //false
    a[0][0] = 6;
        console.log(a);  //[ [ 6, 2, 3 ], 4, 5 ]
        console.log(b);  //[ [ 6, 2, 3 ], 4, 5 ]

     Array的 slice 和 concat 方法 并不是 真正的深拷贝,他们其实是浅拷贝。   递归复制是无法完成的。

    2. jQuery中的 extend 复制方法

    可以用来扩展对象,这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制)。

    //jQuery环境下运行
    //深复制
    var
    obj = { name:'xixi', age:20, company : { name : '腾讯', address : '深圳'} }; var obj_extend = $.extend(true,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。 console.log(obj === obj_extend); //false obj.company.name = "ali"; obj.name = "hei"; console.log(obj); //{name:'hei',age:20,company : { name : 'ali', address : '深圳'} } console.log(obj_extend); //{name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} }
    
    
    //jQuery环境下运行
    //浅复制
    var obj = {
        name:"xixi",
        age:20,
        company : { name : '腾讯', address : '深圳'} 
    };
    var obj_extend = $.extend(false,{}, obj); //extend方法,第一个参数为true,为深拷贝,为false,或者没有为浅拷贝。
    console.log(obj === obj_extend);   //false
    obj.name = "heihei";
    console.log(obj);    //{name:'heihei',age:20,company : { name : '腾讯', address : '深圳'} 
    console.log(obj_extend);  //{name:'xixi',age:20,company : { name : '腾讯', address : '深圳'} 

    总结:Array 的 slice 和 concat 方法 和 jQuery 中的 extend 复制方法,他们都会复制第一层的值,对于 第一层 的值都是 深拷贝,而到 第二层 的时候 Array 的 slice 和 concat 方法就是 复制引用 ,jQuery 中的 extend 复制方法 则 取决于 你的 第一个参数, 也就是是否进行递归复制。所谓第一层 就是 key 所对应的 value 值是基本数据类型,也就像上面栗子中的name、age,而对于 value 值是引用类型 则为第二层,也就像上面例子中的 company。

    3. JSON 对象的 parse 和 stringify

    JOSN 对象中的 stringify 可以把一个 js 对象序列化为一个 JSON 字符串,parse 可以把 JSON 字符串反序列化为一个 js 对象,这两个方法实现的是深拷贝

    var obj = {
        name:'xixi',
        age:20,
        company : { name : '腾讯', address : '深圳'} 
    };
    var obj_json = JSON.parse(JSON.stringify(obj));
    console.log(obj === obj_json);   //false
    obj.company.name = "ali";
    obj.name = "hei";
    console.log(obj);   //{ name: 'hei', age: 20, company: { name: 'ali', address: '深圳' } }
    console.log(obj_json);  //{ name: 'xixi', age: 20, company: { name: '腾讯', address: '深圳' } }
  • 相关阅读:
    邮箱的第99封邮件,第1个Offer
    学校的多媒体网站也模仿Google改版了
    惠普:计算机在非洲大有可为(zz)
    PPLive是不错的东东
    Google增加反病毒功能
    开复给中国学生的第五封信 – 你有选择的权利(zz)
    Yahoo中国变脸?
    拟停止本Blog更新
    在FC4上装GT4.0
    Google CodeJam 中国编程挑战赛拉开帷幕
  • 原文地址:https://www.cnblogs.com/guorange/p/7137621.html
Copyright © 2011-2022 走看看