你將知道:
- “傳遞” 值是什么意思
- 什么是按值傳遞
- 傳遞物品
- JavaScript 中沒有傳遞引用!
介紹
當需要在 JavaScript 中分配或簡單地將一個值傳遞給其他標識符時,我們就會看到通常所說的 按值傳遞 。
嚴格來說,JavaScript 中傳遞值的方式只有一種,那就是復制值,這本質上就是所謂的“按值傳遞”。換句話說,JavaScript 實際上只支持“按值傳遞” 。
然而在 JavaScript 中,絕對沒有辦法通過引用傳遞數據(至少目前是這樣)。
‘傳遞’ 是什么意思?
基本上,每當我們在 JavaScript 中將一個標識符(即變量、常量、屬性等)分配給另一個標識符時,我們所做的事情就是傳遞標識符。傳遞標識符只是將其分配給另一個標識符。
例如,如果我們有一個變量 x
并將其分配給另一個變量 y
,我們會說我們將變量 x
傳遞給 y
。類似地,如果我們將變量 x
作為參數提供給函數 f()
,我們再次說我們正在傳遞變量 x
但這次是傳遞給函數 f()
。
什么是按值傳遞?
按值傳遞是指通過復制其值來傳遞標識符。
在按值傳遞中,傳遞的標識符中存儲的值被復制 ,然后其副本存儲在另一個標識符中。
因此,我們說 “按值傳遞” ,也就是說,我們傳遞存儲的精確值。
var text = 'Hello';
var str = text;text = 'Bye';console.log(str);
那么,代碼將記錄值 'Hello'
首先,我們定義一個變量 text
,并將其初始化為 'Hello'
。然后,我們將 text
賦值給第二個變量 str
。完成后,我們最終修改 text
,然后輸出 str
值。
現在,人們可能會認為,既然 text
已賦值給 str
,那么更改 text
也會導致 str
發生更改;但這并沒有發生。這僅僅是因為 JavaScript 中的原語是按值傳遞的。
當我們將 text
分配給 str
時,將復制存儲在 text
中的實際值 (即 'Hello'
,并將副本分配給 str
。
換句話說,變量 text
和 str
都有各自獨立的 'Hello'
值;改變其中一個不會明顯改變另一個。
上面的代碼從技術上講等同于下面的代碼:
var str = 'Hello'; // own value
var text = 'Hello'; // own valuetext = 'Bye';console.log(str);
JavaScript 數據類型不只有原始類型,對吧?我們還有對象。現在,對象傳遞也是按值傳遞的。
ha?
在 JavaScript 中,對象通過其引用 存儲在標識符中, 而不是通過其實際值。
引用可以被認為是指向存儲對象位置的內存地址。
由于 JavaScript 中的對象通過其引用存儲在標識符內,因此當傳遞該對象時,實際傳遞的是該引用。
對象是真實的數據;引用是對象在程序中的表示方式。
再次強調,需要特別注意的是,對象仍然像 JavaScript 中的原語一樣傳遞,即按值傳遞;對象唯一的不同之處在于它們的存儲方式,即通過引用。
var obj = { x: 10 };
var obj2 = obj;obj.x = 20;console.log(obj2.x); // 20
我們首先定義一個變量 obj
,其值為 { x: 10 }
然后定義另一個變量 obj2
,并將其初始化為 obj
。
接下來,我們改變 obj
的屬性 x
,然后記錄 obj2
的相同屬性。
obj.x
在 obj2
中可見,僅僅是因為 obj
和 obj2
都引用內存中 obj
同一個對象 。obj 和 obj2
不保存單獨的對象 - 它們保存完全相同的對象。
JavaScript 中對象是如何存儲的
這是我們的 obj
變量。它包含一個指向內存中對象 { x: 10 }
的值(箭頭所示)。這個值就是我們所說的引用。
當我們將 obj
賦值給另一個變量 obj2
時,會發生以下情況:
在 JavaScript 中將對象分配給另一個標識符
obj
中存儲的值(引用)僅僅被復制到 obj2
中。因此, obj2
指向(箭頭所示) obj
指向的同一個對象 { x: 10 }
。
如果我們現在繼續更改 obj
的屬性,就像我們在上面的代碼中通過更新屬性 x
所做的那樣,那么該更改在 obj2
中也會可見。
重申一下:
當我們將 obj
分配給 obj2
時, obj
中存儲的實際值 (即引用 )被復制,并將該副本分配給 obj2
。 實際也還是值傳遞,只是這個值是引用。
從今以后,如果我們改變存儲在 obj
(或 obj2
)中的對象,這些變化顯然也會在 obj2
(或 obj
)中可見,因為它們都包含完全相同的對象。
(牢記上面的圖)
JavaScript 中沒有傳遞引用!
你不能真正在 JavaScript 中通過其引用(在內存中)傳遞標識符,并期望其他代碼能夠控制該標識符中存儲的內容。
事實上,很容易確認傳統意義上的 JavaScript 不支持傳遞引用。
以上面部分的代碼為例,如果我們將任何值重新分配給 obj
或 obj2
本身,另一個變量不會發生神奇的變化。
var obj = { x: 10 };
var obj2 = obj; // This is just pass-by-value.obj = 20;console.log(obj2);{ x: 10 }
這里的一切與之前相同,只是現在變量 obj
自身發生了改變(而不是像之前那樣改變其屬性 x
)。然后,直接輸出 obj
,而不是輸出 obj.x
。
因為 JavaScript 中沒有真正意義上的按引用傳遞,所以我們在為 obj
分配值時, obj2
不會改變 - 它會繼續保留 { x: 10 }
。
這純粹是因為沒有任何東西將兩個變量 obj
和 obj2
聯系在一起。
簡單來說就是,本來他倆的值都是引用,比如 16 位一個引用地址,指向了內存中的{x: 10},所以,當 xxx.x 的時候,才會影響這兩個對象,但實際他倆是兩個變量,當 obj = 20 的時候, 那就是一個原語,最基礎的值 20。那么得到的結果當然就是 obj = 20 , obj2 = {x:10}