• js深拷贝与浅拷贝的区别及实现


    1. 对于基本数据类型

    其值在内存中占据着固定大小的空间,并被保存在栈内存中。当一个变量向另一个变量复制基本类型的值,会创建这个值的副本,并且我们不能给基本数据类型的值添加属性。其为深拷贝。

    2. 对于引用类型

     浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存; 改变一个对象,另一个会随之改变;
     深拷贝:复制并创建一个一模一样的对象,不共享内存,修改新对象,旧对象保持不变。

    01 浅拷贝的实现

    var arr = [1, 2, 3, '4'];
    
    var arr2 = arr;
    arr2[1] = "test"; 
    console.log(arr); // [1, "test", 3, "4"]
    console.log(arr2); // [1, "test", 3, "4"]

    我们可以看到,简单的赋值便是浅拷贝,一个对象改变,另一个也随之改变。

    02 深拷贝的实现

    1.使用JSON.stringfy();

    var obj1 = { a: { b: 10 } };
    var obj2 = JSON.parse(JSON.stringify(obj1));
    obj2.a.b = 20;
    console.log(obj1); //{ a: { b: 10 } }  
    console.log(obj2); //{ a: { b: 20 } }
    console.log(obj1 === obj2);   // false
    console.log(obj1.a === obj2.a);   // false

    2.使用递归实现

    function deepClone(obj){
        let objClone = Array.isArray(obj)?[]:{};
        if(obj && typeof obj==="object"){
            for(key in obj){
                //判断ojb子元素是否为对象,如果是,递归复制
                    if(obj[key]&&typeof obj[key] ==="object"){
                        objClone[key] = deepClone(obj[key]);
                    }else{
                        //如果不是,简单复制
                        objClone[key] = obj[key];
                    }
            }
        }
        return objClone;
    }    
    let a=[1,2,3,4],
    b=deepClone(a);
    a[0]=2;
    console.log(a);//[2, 2, 3, 4] 
    console.log(b);// [1, 2, 3, 4]

    当对象中有循环引用时:

    即:

    var a={c:1,d:2};
    a.e=a;

    设置一个标记,当目前对象已经被克隆过时,则不再循环调用

    function deepClone(obj){
       mark[obj]=1;
        let objClone = Array.isArray(obj)?[]:{};
            for(key in obj){
                //判断ojb子元素是否为对象,如果是,递归复制
                    if(obj[key]&&typeof obj[key] ==="object"){
                        if(mark[obj[key]]==1){
                            objClone[key]=obj[key];
                            continue;
                        }
                        objClone[key] = deepClone(obj[key]);
                    }else{
                        //如果不是,简单复制
                        objClone[key] = obj[key];
                    }
            }
        return objClone;
    }    
    var a={c:1,d:2};
    a.e=a;
     mark={};
    b=deepClone(a);
    
    console.log(a);//{c: 1, d: 2, e: {…}}
    console.log(b);//{c: 1, d: 2, e: {…}}

    3.JQuery的extend()。

    $.extend( [deep ], target, object1 [, objectN ] )

    deep表示是否深拷贝,true为深拷贝,false为浅拷贝;

    target object类型 目标对象,其他对象的成员属性将被附加到该对象上。

    object1  objectN可选。 Object类型 第一个以及第N个被合并的对象。 

    let a=[0,1,[2,3],4],
        b=$.extend(true,[],a);
    a[0]=-1;
    a[2][0]=-1;
    console.log(a);//[-1,1,[-1,3],4]
    console.log(b);//[0,1,[2,3],4]

    特别说明:concat(),slice()不是深拷贝,因为其只是一级属性是深拷贝,二级属性就不是了。

    let a=[0,1,[2,3],4],
            b=a.slice();
    a[0]=-1;
    a[2][0]=-1;
    console.log(a);//[-1,1,[-1,3],4]
    console.log(b);//[0,1,[-1,3],4]
    let a=[0,1,[2,3],4],
            b=[].concat(a);
    a[0]=-1;
    a[2][0]=-1;
    console.log(a);//[-1,1,[-1,3],4]
    console.log(b);//[0,1,[-1,3],4]
  • 相关阅读:
    mongoGridFS
    ModelClientValidationRule同时存在多个位置解决方案
    C# 使用 SocketAsyncEventArgs 实现UdpSocket系列
    如何把握机会
    c#异步socket
    服务器×××上的MSDTC不可用解决办法
    分享.net常见的内存泄露及解决方法
    如何处理几十万条并发数据
    iphone开发,模拟器生成文件路径
    Iphone隐藏和显示TabBar的方法
  • 原文地址:https://www.cnblogs.com/sunmarvell/p/9384948.html
Copyright © 2020-2023  润新知