基本型別
假設我們有兩個變數a和b分別設定為 10,接著把b的值等於a;最後再把a的值改為20。
1 | var a = 10; |
變數 c 的值是透過複製變數 a 的值而來。
但變數 a 更新之後,不會去影響變數 c 的數值。
表面上看起來變數 c 的內容是透過複製變數 a 而來,但此時若變數 a 的內容為基本型別時,實際上變數 c 是去建立了一個新的值,然後將變數 a 的內容複製了一份過來。
Call By Value
當我們在建立「基本型別」 的變數時,根據上面的例子,a 會存在記憶體中的某個位置。這時候,當我指定另一個變數 c,它的值等同於 a 的時候,c 實際上會建立另一個獨立的記憶體位置,接著再把 a 的值存在這個獨立的記憶體位置。也就是說, a 和 b 其實是存在於兩個不同的記憶體位置,因此彼此並不會乎相干擾影響,這種情況,我們就稱為 Call By Value 。
物件型別
JavaScript 的物件都應該看作是一個「實體」。
1 | var a= { value: 10 }; |
「物件」在 JavaScript 中是透過「引用」的方式傳遞資料的,當 a.value 的內容被更新了之後,連帶著 b.value 也跟著改變。
Call By Reference
當我將變數 a 設立成一個 Object 時,一樣會存在記憶體中的某個位置;但是當我建立一個變數 b,並且把變數 b 的值等同於 a 時,這時候並不會再給予它一個新的位置,而是將 b 指定到物件 a 的位置,讓變數 a 和 b 使用相同的記憶體位置,因此,當 a 的值改變的時候 b 的值也會改變,這種情形我們就稱為 Call By Reference。
例外情況
如果使用 object literal 的方式指定物件的值,那麼就會是 Call by value:
1 | var a= { value: 10 }; |
在這種情況下,因為它並不清楚 a 的內容是已經存在的,所以會建立一個新的記憶體位置來存放 a 物件裡面的內容。
Call by sharing
JavaScript 實際上是另一種稱做「call by sharing」的模式,其特點在於,當 function 的參數,如 function changeValue(obj){ ... } 中的 obj 被重新賦值的時候,外部變數的內容是不會被影響的。
1 | var a= { value: 10 }; |
如果不是重新賦值的情況,則又會回到傳址的方式:
1 | var a = { value: 10 }; |