JS 深浅拷贝的区别以及实现方式

Posted 女神爱大雄

tags:

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

在学习JS时最让我头疼的就是栈和堆以及一切概念性的问题 也是最近才把想给这个搞通提上了日程

简单来说 深浅拷贝的区别:

   A复制了B 当改变 A 中的一个元素 B 中的这个元素也改变了 这就叫做浅拷贝

  反之 改变 A 中的元素 B 中的元素并没有一起改变 这就叫做 深拷贝  深拷贝都是针对于较为复杂的object类型

  这个也就要牵扯到栈和堆 以及 数据类型的概念了

  JS几大基本数据类型: Null Undefined Number Boolean String Object Symbol(唯一值) BigInt(ES10未来 任意精度整数)

  引用类型:Object类 --- 常规名值对的无序对象{a: 1} 数组:[1, 2] 函数等

  1、基本类型 --- 名值都储存再栈内存中; let a = 1

    

 

 

   当 b = a 复制时; 栈内存会新开辟一个内存

  

 

 

   所以当你修改 a = 2 时 b 的值并不会发生改变  但这也算不上深拷贝 因为深拷贝都是针对于较为复杂的object类型

  2、引用类型 名存栈内存中 值存堆内存中 但是栈内存会提供一个引用地址指向堆内存中的值

  

 

  所以当 a = b 进行拷贝的时候 复制的是 a 的引用地址 而非堆里面的值

 

   

  当我们 a [0] = 7 时 由于 a 和 b 指向的都是同一个堆内存值 所以 a 的修改 影响到了 b  这就是所谓的浅拷贝

  

 

 

   所以要实现深拷贝 就是要在堆内存中新建一个 b 的堆内存

  

 

  实现深拷贝

  function deepClone(obj){

    let a = JSON.stringify(obj);

    b = JSON.parse(a)

    return b 

  }

  let a = [0, 1, [3,4], 9]

  b = deepClone(a)

  a[2][0] = 7

  console.log(a, b) //[0,1,[7,4],9] [0, 1, [3,4], 9]

  

  JSON.stringify() 和 JSON.parse() 的区别

  JSON.stringify() 将对象转换为 JSON字符串 而 JSON.parse() 则是将JSON字符串转换为 对象

  但是在使用JSON.parse()时   所转换的JSON字符串必须要符合JOSN格式 即键值都需要 "" 进行包裹

 

 let a = \'["1","2"]\';
 let b = "[\'1\',\'2\']";
 console.log(JSON.parse(a));// Array [1,2]
 console.log(JSON.parse(b));// 报错
  

 

   递归方式实现:

  

function deepClone(obj){
  let objClone = Array.isArray(obj)?[]:{};
  if(obj && typeof obj==="object"){
    for(key in obj){
      if(obj.hasOwnProperty(key)){
      //判断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,b);

 

 

   

  数组放 splice  concat slice 都不是真正的深拷贝 在一级层级是没问题的 当有二层层级时  就会被影响

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

 


 

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

 


 

 

 

 

 

以上是关于JS 深浅拷贝的区别以及实现方式的主要内容,如果未能解决你的问题,请参考以下文章

学姐面试宝典前端基础篇Ⅴ——JS深浅拷贝箭头函数事件监听等

论基本数据类型与引用数据类型以及深浅拷贝的区别

javascript的深浅拷贝

js深拷贝和浅拷贝区别,以及实现深拷贝的方式

Spring Boot 深拷贝对象

吃透Js深入学习浅拷贝和深拷贝