Try   HackMD

物件傳參考|筆記 by Sz

tags: Sz 課前 Vue新手夏令營

備註

找資料的時候看到很多種說法,可能要留意一下是不是在講同件事XD
傳參照、傳參、call by reference、pass by reference

傳?傳什麼?

參考是什麼?

參考(參照、reference) ,指的是他們存在的記憶體空間
傳參考會共用同一個記憶體空間,不會複製

JS 的傳值與傳參考

傳值 Call By Value

  • 把 value 傳到另一個記憶體位置的 value 上,是 copy 非 link
  • JS 中的純值就是這個特性(Boolean、Null、Undefined、Number、String)
  • 彼此只有 copy 關係,所以 copy 完後,其中一方被更改,不會影響到另一方

傳參考 Call By Reference

  • 把記憶位置傳到另一個物件的記憶體位置上,為 link 非 copy
  • JS 中物件型別(這個詞不太懂,包含 function, array)是這個特性
  • 彼此有 link 關係,所以在哪裡其中一方被修改了,兩邊都會更新

Object 的傳參考特性

不論物件、陣列都是用傳參考方式賦值,
賦值後彼此有 link 關係,其中一方被更改,兩方都會一起更新

有個 person 物件

const person = {
  name: '小明',
  obj: {}
}

person2 與 person 建立了一個 link 關係
在 person2 裡不論更改 key, 或是內部 obj 的 key 都會更新原本資料

const person2 = person;  // link 了一個 person2 物件
person2.name = '杰倫';   // 在 person2 更新這個物件內容
person.name = person2.name = '杰倫';  // 兩邊都會自動更新

object 在 object 內部也一樣擁有傳參考特性

再額外建立一個 obj2 跟 obj 建立 link 關係(還不知道為什麼要這麼做)
直接打 person2.obj.{key} 也會更新 person.obj

const obj2 = obj // 建立新的 link

Danger Zone

透過 function 修改 object 的 key (不清楚自己在幹嘛不要亂用)

有個 funciton 專門修改 object 的某個 key

const fn = (item) => {
  item.name = '杰倫';
}

不論這個 function 帶入 person, person2 都會被更新

fn(person2);   // 透過這個 function 去修改 person2(跟 person 有 link 相關)
console.log(person);  // 物件傳參考特性, person 也會被更新

斬斷一切的牽連:淺層拷貝、深層拷貝

開發時如果沒有留意到傳參考特性,會很容易不小心修改到原本的資料
避免此狀況可使用

淺層拷貝(Shallow Copy)

最外層的 object 是新建的,內層若有其他 object 還是保留傳參考特性,程式碼較單純

Object.assign()

const newObject = Object.assign({}, originObject)
  • 第一個 parameter 放空的 object (建立新的記憶體空間)
  • 第二個放想要複製的 object
    • 在空 object 中展開想要複製的物件

在新的空 object 內展開

const newObject2 = {
    ...originObject
}

深層拷貝(Deep Copy)

將轉為字串再轉回 object 的 object 賦值在 newObject 上
兩者已經沒有關係了

const newObject = JSON.parse(JSON.stringify(object))