前言
上次提到 Primitive Types 與 object 的其中一個差別,接下來我們討論另一個差別,那就是對於運算子「=」,兩者的表現並不一樣。
使用運算子「=」賦值
賦值就像字面上的意思一樣,重新給予一個值,而我們也可以喚醒另外一個世界線的記憶:
這也達到了當初做筆記的目的,因為有之前的筆記,所以我在學習相同的觀念但不同講法時,我可以交叉驗證自己吸收得如何。
由另個世界線的記憶我們可以知道:
- 「=」的優先性為 3
- 「=」為「右相依」 (right-to-left)
- Primitive Types 是傳值 (By Value) 的
- Object 是傳參考 (By Reference) 的
例子驗證
1 | var a = 10; |
上面這個如我們預期,因為 Primitive Types 是傳值的,我們創造一個新的變數 a
,並且令 b = a
,變數 b
會指向一個新的記憶體位址,並拷貝那個純值 10 ,放到新的記憶體位址。
接下來做點改變
1 | var obj = { |
首先使用物件實體語法建立了 obj
物件,接著使用等號運算子將右邊的 obj
給 obj2
,而物件是傳參考的,也就是說這兩個物件目前指向的記憶體位址相同,所以結果才會是這樣。
上面算是一個小複習,畢竟在另個世界線有同樣的範例了。
然而 Array 在最底層也是物件,所以傳參考的情況也適用:
1 | var arr1 = []; |
以上就是 Primitive Types 與 object 的另一個差別。
「=」的小陷阱
延續上面那個物件的例子,如果改成這樣:
1 | var obj = { |
雖然上面提到物件是傳參考的,但是在這個例子中雖然 obj2
與 obj
一度指向同樣的記憶體位址,但是隨即又被等號運算子重新賦與一個新的物件,此時 obj
就與 obj2
指向不同的記憶體位址了。
所以陷阱在哪裡
透過上下兩個相似例子的比較,我們需要搞清楚以下:
obj2.num = 20;
obj2 = { num: 20 };
雖然都是使用等號運算子,但是意義上是不太一樣的。
回想一下第一點的那個例子,
- 一開始
obj
與obj2
指向同一個位址 - 使用等號運算子把新的數值賦值給
obj2
內的屬性num
- 新的數值產生也會被存放在某個記憶體位址,
- 但因為賦值的對象並不是
obj2
,所以沒有影響到obj2
的位址。
第二點的例子,
- 一開始
obj
與obj2
指向同一個位址 - 使用等號運算子把新的物件賦值給
obj2
- 新的物件產生也會被存放在某個記憶體位址
- 此時賦值的對象是
obj2
,等號運算子把新物件的記憶體位址給了obj2
也就是說,此時 obj
與 obj2
就不相干了。
另外還有個初學者會遇到的例子,關於等號運算子的,也就是少打等號的問題,一般我們都會這樣寫
1 | var a = 1; |
但如果少打了等號:
1 | var a = 1; |
結果就會出現非預期的輸出,原因是這樣子寫就如同:
1 | var a = 1; |
所以這個 if 內的東西一定會執行。
[心得]
這個小節的內容個各別散落在原本世界線的不同文章上,透過這樣的重新整理,又再次的複習了這些概念,其中我最喜歡的是小陷阱的部分,可以藉由這些陷阱,再度的仔細思考是不是哪個環節想錯了。
我開始喜歡寫紀錄文了,這有點像鄧不利多的儲思盆,可以把記不住的東西給寫下來,然後不占據腦容量,需要的時候在到儲思盆看一下~
雖然暫時沒辦法全部都記住,看久、摸久、寫久總會是我的。