整理 [JS101] 裡提到的〈從 Object 的等號真正的理解變數〉相關內容。
console.log([] === []) // false
console.log([1] === [1]) // false
console.log({} === {}) // false
console.log({a:1} === {a:1}) // false
上面的判斷式,兩邊長一樣,console.log 出來應該都會是 true,但為什麼結果全都是 false 呢?課程中是以記憶體位置不同的概念解說。我自己嘗試轉換成用不同形狀的容器養魚的方法去理解。

就算 {} === {} 等號兩邊的物件長得一樣,但只是魚缸裡的魚長一樣,但他們分別被養在不同形狀的魚缸(記憶體位置)裡,連同魚缸一起看魚的話,會發現兩邊其實是不同的,所以才會是 false。
情況一
var obj = {
a: 1
}
var obj2 = obj
console.log(obj2 === obj) // true
當今天宣告一個物件 obj,再宣告另外的物件 obj2 為 obj 時,就像是 obj 跟 obj2一起用魚缸養魚,所以 obj2 會等同於 obj。

情況二
var obj = {
a: 1
}
var obj2 = obj
obj2.a = 2
console.log(obj2 === obj) // true
因為 obj 和 obj2 一起用魚缸養了魚,所以今天 obj2 在魚缸裡加東西,obj 也會跟著變,obj 還是等同於 obj2。

情況三
var obj = {
a: 1
}
var obj2 = obj
obj2 = {
a: 1
}
console.log(obj2 === obj) // false
但當今天 obj2 給整個變數新的物件時(就算新的物件裡屬性和值都和 obj 一樣),就像是 obj2 拿了個新的魚缸養魚。所以 obj 就不同於 obj2了。

情況四
var a = 2
var b = a
b = 3
console.log(a === b) // false
而如果是 primitive type 的話,變數所宣告的值都是獨立的個體。所以儘管 b = a,但後續更動 b 的值跟 a 是無關的。

使用 function 注意事項
理解了前述的觀念,就可以理解 function 傳進 parameter 的運作機制:
function swap(a, b) {
var temp = a
a = b
b = temp
}
var num1 = 10
var num2 = 20
console.log(num1, num2) // 10 20
swap(num1, num2)
console.log(num1,num2) // 10 20
因為丟到 function 裡的參數是複製一份的,所以儘管在 function 裡面數值確實有交換,但不會改變到外面的 num1 和 num2 的值。

傳物件進 function 的情況
function addValue(obj) {
obj = {
number: 30
}
console.log('addValue', obj)
return 1
}
var a = {
number: 10
}
addValue(a)
console.log(a) // 11
而傳物件進去的情況,因為是放魚缸進去一起養魚,所以如果改變屬性,物件 a 的值會跟著改變。

Immutable 觀念
primitive type 的值是不可變的,所以今天要對原變數做什麼更動的話,都再賦一次值。

物件的話則有 mutator method 會更動到原陣列、原物件,所以使用的時候要注意。


