整理 [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 會更動到原陣列、原物件,所以使用的時候要注意。