深拷贝与浅拷贝

Posted menggirl23

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深拷贝与浅拷贝相关的知识,希望对你有一定的参考价值。

 在工作中很多情况下会用到拷贝,但是有时候拷贝后会引起一些问题。比如拷贝对象时用的是浅拷贝,那么在修改拷贝对象的值后,源对象也会变化,这当然不是咱希望的,所以在拷贝时要多想想适合用哪种拷贝方法。

数据类型分为

  基本数据类型:number、string、Null、Undefined、boolean、Symbol(ES6),这些数据类型可以直接操作保存在变量中的值,他们都是存放在栈中的简单变量,数据大小确定,内存空间大小可以分配,

  拷贝对象与源对象是分别保存在栈内存的不同内存中的,两者不会互相影响,如下图

  当b=a复制时,栈内存会新开辟一个内存,a和b不会相互影响,所以此时修改b后,a不会发生变化。

  技术分享图片            技术分享图片

     

  引用数据类型:Object类(包括键值对{name:"zhangsan"},数组[1,2,3],函数等),引用数据的名存在栈内存中,值存在于堆内存中,但是栈内存会提供一个引用的地址指向堆内存中的值。

  当bb = aa复制时,栈内存中新开了一个内存,但是bb的val的堆地址指向了aa的堆地址,也就是aa和bb的val引用了同一个堆地址的值,所以当其中一个的val变化时,另一个也会随着变化。 

  技术分享图片技术分享图片

 

拷贝的基本概念

  深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。

  浅拷贝就是拷贝指向对象的指针,意思就是说:拷贝出来的目标对象的指针和源对象的指针指向的内存空间是同一块空间,浅拷贝只是一种简单的拷贝,让几个对象公用一个内存,然而当内存销毁的时候,指向这个内存空间的所有指针需要重新定义,不然会造成指针错误。

   下面这张图画出了深拷贝与浅拷贝的区别

  技术分享图片

深拷贝的方法

   1、递归

    用递归的方式封装一个深拷贝的方法deepClone

      function deepClone(obj){
            if(obj && typeof obj === "object"){
                let coloneObj = Array.isArray(obj) ? [] : {};
                for(key in obj){
                    if(obj.hasOwnProperty(key)){//判断对象自身属性中是否具有指定的属性
                        if(obj[key] && typeof obj[key] === "object"){//判断obj的属性是否为object,如果是,继续进行深拷贝
                            coloneObj[key] = deepClone(obj[key]);
                        }else{
                            coloneObj[key] = obj[key];
                        }
                    }
                }
                return coloneObj;
            }
        }
        var person1 = {name:"zhangsan",age:"18"};//创建一个person1
        var clonePerson = deepClone(person1);//深拷贝出一个clonePerson
        clonePerson.name = "lisi";//修改clonePerson的name字段
        console.log(person1,clonePerson);//打印出person1和clonePerson

    下图是代码运行结果,此时两个变量相互独立的,不会影响对方。

  技术分享图片

 

  2、JSON.stringify()和JSON.parse()

    结合JSON的JSON.stringify()JSON.parse()这两个方法完成深拷贝

        function deepCloneByJSON(obj){
            let objArr = JSON.stringify(obj);//javascript 值转换为 JSON 字符串。
            let cloneObjByJson = JSON.parse(objArr);//将一个 JSON 字符串转换为对象。
            return cloneObjByJson;
        }
        var json1 = {type:"byjson",name:"json1"};
        var cloneJson = deepCloneByJSON(json1);
        cloneJson.name = "clonejson";
        console.log(json1,cloneJson);

    下图是代码运行结果,此时两个变量相互独立的,不会影响对方。

    技术分享图片

  3、JQuery的extend方法

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

    如果不指定target,则给jQuery命名空间本身进行扩展。这有助于插件作者为jQuery增加新方法。

    如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 

 

    

以上就是关于深拷贝和浅拷贝的笔记,其中有不对的地方欢迎大家指正!


以上是关于深拷贝与浅拷贝的主要内容,如果未能解决你的问题,请参考以下文章

iOS开发——深拷贝与浅拷贝详解

iOS之深拷贝与浅拷贝

python 的深拷贝与浅拷贝

JavaScript深拷贝与浅拷贝

JavaSE知识集锦深拷贝与浅拷贝

深拷贝与浅拷贝详解