當前位置 主頁 > 網站技術 > 代碼類 > 最大化 縮小

    javascript 關于賦值、淺拷貝、深拷貝的個人理解

    欄目:代碼類 時間:2019-11-02 06:06

    一、棧、堆、指針地址

      棧內存:個人理解是,基本數據類型和引用數據類型都會用到的一個空間,這個空間以key-value形式存在,value本身不可修改,只能賦值替換;

      堆內存:堆,就是堆積,每一個被開辟的空間可以想象成一個空紙盒子,紙盒子所在的紙盒子堆就是 “堆” 。基本數據類型沒有堆的概念。堆,只針對引用數據類型。存儲方式應該是以對象(object)形式保存,對象內容包含key-value形式數據,value本身同樣不可修改,只能賦值替換;

      指針地址:針對引用數據類型在棧保存的值就是指針地址,地址指向保存在堆里面的對象。

    二、賦值

      賦值分兩個,一個是基本數據類型的賦值,一個是引用數據類型的賦值,基本數據類型賦的是 “值”,引用數據類型賦的是 “指針地址”。

    1.基本數據類型賦值

    //在棧內開辟一個空間,空間名稱叫a,存放值1;
    var a = 1;
    
    //在棧內開辟一個空間,空間名字叫b。接著先把a的值1復制一份,然后存放進b
    var b = a;

    如下圖:

    2.引用數據類型賦值

    //首先在棧開辟一個空間a存放指針地址,設指針地址為address1;同時會在堆里面開辟一個空間放置對象數據 2 var a = {
     no: 1,
     per: {
      name: "jack"
     },
     per2: {
      name: "rose"
     }
    }
    
    //a賦值給b,此時b會在棧開辟一個空間b,用來放置address1,這個指針指向a所在堆的對象數據
    var b = a;
    
    //修改賦值后的值b,其實就是修改b的指針address1所指向的對象數據
    b.no = 1314;
    
    //修改b會影響原數據(所有層次的數據都會影響)
    //這個原數據其實不是原數據,因為a和b其實都是同一個數據
    //就像從中國去美國,可以從a地點(比如北京)或者b地點(比如上海)坐飛機去,但是到達的都是同一個地方(也就是對象數據)
    b.per.name = "王五";
    
    console.log(a, b)

    上面代碼打印如圖:

     

    對b的修改會影響a原本的值。對a的修改同樣會同步b的值,對a的修改本人沒有寫出,你們可以自己試試,結果是一樣的。

      針對上面的代碼,引用數據類型賦值,如下圖所示:

    無論修改a對象還是b對象,都是在修改 “obj” 這個對象

    三、淺拷貝

       引用數據類型的淺拷貝,代碼如下:

    //在棧開辟一個空間a,存放a的指針地址,設指針地址為address2a,同時在堆開辟一個空間,設這空間為A,存放a對象數據
    var a = {
     no: 1,
     per: {
      name: "jack",
     },
     per2: {
      name: "rose"
     }
    }
    
    //在棧開辟一個空間b,存放b的指針地址,設指針地址為address2b,同時在堆開辟一個空間,設這空間為B,存放b對象數據
    var b = {};
    
    //對a的數據進行循環,判斷如果有key,就把值賦到B對應的key位置
    //這個循環,遇到數據類型為基本數據類型,賦的是值;遇到引用數據類型,賦的是指針地址
    for(var p in a) {
     if(a.hasOwnProperty(p)) {
      b[p] = a[p]
     }
    }
    
    //對b的第一層修改
    b.no = 1314;
    b.per2 = [];
    
    //對b的第二層修改
    b.per.name = "王五";
    
    //淺拷貝,修改b后,第一層修改都不影響原數據,第二層以及以上層次的修改都影響原數據
    //當前沒有寫第三層及以上層次,可自行測試。
    console.log(a, b)

    運行結果如圖:

    可以理解為,a原本的東西被完全復制了一份,放到了b里面,然會對b的操作,就只關b的事情了。a原本是什么值,現在依然是什么值,b的修改對a完全沒有影響。

在线观看中文字幕理论片