因為會忘,所以要寫下來

Angular 淺拷貝之日記文

又踩雷啦啊哈哈哈哈哈。 來重現一下遇到的情境吧


bug 出現


export class AppComponent implements OnInit {
  fruit : any = {
    apple: {},
    banana: {},
  };

  ngOnInit() {
    this.fruit = {
      apple: {
        id: 1,
        isSelect: false,
      },
      banana: {
        id: 2,
        isSelect: false,
      },
    };
  }

  onClick(isSelect: boolean) {
    this.fruit = {
      apple: {
        id: 1,
        isSelect,
      },
    };
  }

  • 一開始建了一個 fruit 的物件,裡面有 applebanana 這兩樣空物件
  • OnInit 時,賦予了 applebanana
  • 當我按下 button Click 的 時後, apple 裡的 isSelect 為 true

啊!踩到雷了!

如圖,按下去後,噴錯了!

發現 banana 的 id 不見了,原來是我把 this.fruit 整個值給改掉了 本以為上述的寫法,只會修改我有填的值 XD


解法:解構賦值 => 淺拷貝(shallow copy)

這裡我使用了 js 裡的解構賦值處理,也可以用來做 淺拷貝(shallow copy) 將 onClick 的寫測改成這樣

onClick(isSelect: boolean) {
  this.fruit = {
    ...this.fruit,  // shallow copy
    apple: {
      id: 1,
      isSelect,
    },
  };
}

來看看成果。嗯…沒噴錯了 XD 結案!


筆記:深拷貝 (deep copy)

將原本的物件轉字串後再轉成物件,就會又是全新的一個物件了!

JSON.parse(JSON.stringify(objArray));

objArray 為要帶入的物件


後記:

本來以為是淺(深)拷貝的問題,後來仔細一看,原來是我自己搞錯了,將 this.fruit 裡面的整個值都蓋掉,所以才會噴錯,不過剛好也來認識一下 深拷貝與淺拷貝的這件事囉。

案例:https://stackblitz.com/edit/angular-ivy-wvmptw

參考資料:

变量的解构赋值 深入探討 JavaScript 中的參數傳遞:call by value 還是 reference? 關於 JS 中的淺拷貝(shallow copy)以及深拷貝(deep copy)


對這篇文章有什麼想法嗎?

Copyright © 2022 Mandy. All rights reserved. Build with Angular