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);

 

 
        

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM