浅谈浅拷贝和深拷贝

421 阅读3分钟
  • ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。
  • 基本数据类型:Boolean、Null、Undefined、Number、String、Symbol
  • 引用数据类型:Object、Array、Function
  • 基本类型值:指的是那些保存在栈内存中的简单数据段,即这种值完全保存在内存中的一个位置。
  • 引用类型值:指那些保存堆内存中的对象,意思是变量中保存的实际上只是一个指针,这个指针指向内存中的另一个位置,该位置保存对象。
  • 深拷贝与浅拷贝的概念只存在于引用类型
  • 简单的说
    • 浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。
    • 深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。
  • 也可以这样理解
    • 浅拷贝:对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。注意:当内存销毁的时候,指向对象的指针,必须重新定义,才能够使用。

    • 深拷贝:深拷贝是指,拷贝对象的具体内容,两内存地址是自主分配的,拷贝结束之后俩个对象虽然存的值是一样的,但是内存地址不一样,俩个对象页互相不影响,互不干涉。

    • 浅拷贝

      • var a = {x:1}
      • var b = a
      • console.log(b);//{x:1}
      • b.x = 2
      • console.log(b)//{x:2}
      • console.log(a)//{x:2}
    • 浅拷贝是一个传址,也就是把a的值赋给b的时候同时也把a的址赋给了b,当b(a)的值改变的时候,a(b)的值同时也会改变

  • 深拷贝
- 深拷贝的几种方法
1、JSON内置的方法
  - var a={x:1}
  - var b=JSON.parse(JSON.stringfiy(a))
  - console.log(b)//{x:1}
  - b.x=2
  - console.log(b)//{x:2}
  • 原理:用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一来一回之间,新的对象产生了,而且对象会开辟新的栈,实现深拷贝(注:如果对象属性为function,因为JSON格式字符串不支持function,在构建的时候会自动删除)
2、Object的内置方法assign
- var a={x:1}
- var b=Object.assign({}, a);
- console.log(b);    //{x:1}
- b.x = 2;
- console.log(b);    //{x:2}
- console.log(a);    //{x:1}
- 原理:该方法是用Object.assign对对象进行拼接,将后续对象的内容插入到第一个参数指定的对象,不会修改第一个参数之后的对象,而我们将第一个对象指定为一个匿名空对象,实现深拷贝(注:对象嵌套层次过深,超过2层,就会出现浅拷贝的状况,比如echarts组件的option对象)
3、递归实现
- function extendDeepCopy(obj,newobj){
- var newobj=newobj||{};
- for(var i in obj){
- if(typeof obj[i]=='object'){ //确定类型
- newobj[i]=(obj[i].constructor==="Array")?[]:{};
- }else{
- newobj[i]=obj[i];
- }
- }
- return newobj;//结束函数完成深拷贝
- }