zoukankan      html  css  js  c++  java
  • 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);
    
    

     

     
  • 相关阅读:
    Introduction to Machine Learning
    IEEE 802.3 Ethernet
    Introduction to Computer Networks(网络架构与七层参考模式)
    Integral类型的跨平台使用
    Aggregate类型以及值初始化
    合成的默认构造函数定义为delete的一种情况(针对C++11标准)
    版本控制工具Git
    编程实现计算器
    Linux客户/服务器程序设计范式2——并发服务器(进程池)
    Linux客户/服务器程序设计范式1——并发服务器(多进程)
  • 原文地址:https://www.cnblogs.com/qlb-7/p/12957968.html
Copyright © 2011-2022 走看看