美文网首页
对象深浅拷贝

对象深浅拷贝

作者: xiaolizhenzhen | 来源:发表于2018-02-07 14:24 被阅读0次

    关于对象的深浅拷贝,个人有以下几点见解:

    1.深拷贝和浅拷贝只针对像Object, Array这样的引用类型数据。

    2.浅拷贝是对对象引用地址进行拷贝,并没有开辟新的栈,也就是拷贝后的结果是两个对象指向同一个引用地址,修改其中一个对象的属性,则另一个对象的属性也会改变。

    3.深拷贝则是开启一个新的栈,两个对象对应两个不同的引用地址,修改一个对象的属性,不会改变另一个对象的属性。

    image.png image.png

    真-深拷贝

    看着深浅拷贝,区别写法很简单,但是那个上面的深拷贝写法是有问题的。看下面案例:

    var arr=[{a:1,b:2},{a:3,b:4}]
    var newArr=Object.assign([],arr)
    //截断数组
    newArr.length=1
    console.log(newArr)//[{a:1,b:2}]
    console.log(arr)//[{a:1,b:2},{a:3,b:4}]
    //操作newArr,这里看着对arr没影响,实际上已经挖了一个坑,下面就跳进去
    newArr[0].a=123
    //修改newArr[0]这个对象,也是影响了arr[0]这个对象
    console.log(arr[0])//{a: 123, b: 2}
    
    

    为什么会这样呢,因为Object.assign并不是深拷贝,是披着深拷贝外衣的浅拷贝。最多也是Object.assign会课拷贝第一层的值,对于第一层的值都是深拷贝,而到第二层的时候就是 复制引用。类似的情况还有,slice方法和concat方法等。要解决这个问题,就得自己封装方法!如下:

    //利用递归来实现深拷贝,如果对象属性的值是引用类型(Array,Object),
    //那么对该属性进行深拷贝,直到遍历到属性的值是基本类型为止。 
    
    function deepClone(obj){    
      if(obj === null) return null 
        if(typeof obj !== 'object') return obj;
        if(obj.constructor===Date) return new Date(obj); 
        if(obj.constructor === RegExp) return new RegExp(obj);
        var newObj = new obj.constructor ();  //保持继承链
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {   //不遍历其原型链上的属性
                var val = obj[key];
                newObj[key] = typeof val === 'object' ? arguments.callee(val) : val; // 使用arguments.callee解除与函数名的耦合
            }
        }  
        return newObj;  
    }
    // 测试
    var arr=[{a:1,b:2},{a:3,b:4}]
    var newArr=deepClone(arr)
    console.log(arr[0])//{a:1,b:2}
    newArr[0].a=123
    console.log(arr[0])//{a:1,b:2}
    
    

    还有一个方法就是简单粗暴法,我现在在用的一个方法!原理很简单,就是先把对象转成字符串,再把字符串转成对象!也能实现同样效果。

    var newArr2=JSON.parse(JSON.stringify(arr));
    console.log(arr[0])//{a:1,b:2}
    newArr2[0].a=123
    console.log(arr[0])//{a:1,b:2}
    

    jquery 中$.extend()也可以实现深拷贝

    $.extend( [deep ], target, object1 [, objectN ] )
    
    
    • deep
      类型: Boolean
      如果是true,合并成为递归(又叫做深拷贝)。
    • target
      类型: Object
      对象扩展。这将接收新的属性。
    • object1
      类型: Object
      一个对象,它包含额外的属性合并到第一个参数。
    • objectN
      类型: Object
      包含额外的属性合并到第一个参数。

    参考网址:

    JavaScript 实用技巧

    JS中如何进行对象的深拷贝

    相关文章

      网友评论

          本文标题:对象深浅拷贝

          本文链接:https://www.haomeiwen.com/subject/akwkwxtx.html