David Yu Blog

Javascript 物件傳址

Word count: 424Reading time: 2 min
2022/11/30

物件傳址 Call by reference

1
2
3
4
let obj1 = { a: 1 }
let obj2 = { a: 1 }

console.log(obj1 === obj2) // false

為啥obj1 === obj2會等於false呢?

因為在JS中,每個物件都是獨立存在的個體,在比較物件型別時,比較的是記憶體位置,亦即參考(reference),而非值(value)。

物件內容比較

JSON.stringify()

1
2
3
4
5
6

let a = { x: 5, y: 6 }
let b = { x: 5, y: 6 }

console.log(a === b); // false
console.log(JSON.stringify(a) === JSON.stringify(b)); // true

物件拷貝

主要分為淺拷貝、深拷貝

淺拷貝

  1. 把物件內容複製到一個空物件裡面

    1
    2
    3
    4
    let obj1 = { a: 1 }
    let obj2 = Object.assign({}, obj)

    console.log(obj2) // { a: 1 }
  2. 使用...物件展開運算子

    1
    2
    3
    4
    let obj1 = { a: 1 }
    let obj2 = { ...obj1 }

    console.log(obj2) // { a: 1 }

淺拷貝缺點

1
2
3
4
5
6
7
8
9
10
11
let obj1 = {
a: 10,
b: {
foo: 20,
},
}

let obj2 = { ...obj1 }

obj1 === obj2 // console.log: false
obj1.b === obj2.b // console.log: true

可以注意到內層的物件還是指向相同記憶體位置。所以淺拷貝只有改變外層容器的地址,沒動到內層。

深拷貝

解決淺拷貝的缺點,完全複製一份

1
2
3
4
5
6
7
8
9
10
11
let obj1 = {
a: 10,
b: {
foo: 20,
},
}

let obj2 = JSON.parse(JSON.stringify(obj1))

obj1 === obj2 // console.log: false
obj1.b === obj2.b // console.log: false

先用JSON.stringify把obj1轉成JSON string,再用JSON.parse轉成物件,就可以完成複製

深拷貝缺點

JSON.stringify會自動過濾掉key 為 symbol 或值為 undefined 的屬性

詳細的解決可參考:

https://blog.techbridge.cc/2018/06/23/javascript-call-by-value-or-reference/

參考文章

  1. https://hackmd.io/@chupai/B13YRDJJB#JavaScript-的「傳值」與「傳址」
  2. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify
CATALOG
  1. 1. 物件傳址 Call by reference
  2. 2. 物件內容比較
  3. 3. 物件拷貝
    1. 3.1. 淺拷貝
    2. 3.2. 淺拷貝缺點
    3. 3.3. 深拷貝
    4. 3.4. 深拷貝缺點