引用js_js值和引用
值和引用
在許多編程語言中,賦值和參數(shù)傳遞可以通過值復(fù)制或者引用復(fù)制來完成,這取決于我們使用什么語法。
例如,在 C++ 中如果要向函數(shù)傳遞一個數(shù)字并在函數(shù)中更改它的值,就可以這樣來聲明參 數(shù) int& myNum,即如果傳遞的變量是 x,myNum 就是指向 x 的引用。引用就像一種特殊的指 針,是來指向變量的指針(別名)。如果參數(shù)不聲明為引用的話,參數(shù)值總是通過值復(fù)制 的方式傳遞,即便對復(fù)雜的對象值也是如此。
JavaScript 中沒有指針,引用的工作機制也不盡相同。在 JavaScript 中變量不可能成為指向 另一個變量的引用。
JavaScript 引用指向的是值。如果一個值有 10 個引用,這些引用指向的都是同一個值,它 們相互之間沒有引用 / 指向關(guān)系。
JavaScript 對值和引用的賦值 / 傳遞在語法上沒有區(qū)別,完全根據(jù)值的類型來決定
下面來看一個例子:
簡單值(即標量基本類型值,scalar primitive)總是通過值復(fù)制的方式來賦值 / 傳遞,包括 null、undefined、字符串、數(shù)字、布爾和 ES6 中的 symbol。
復(fù)合值(compound value)——對象(包括數(shù)組和封裝對象)和函數(shù),則總 是通過引用復(fù)制的方式來賦值 / 傳遞。
上例中 2 是一個標量基本類型值,所以變量 a 持有該值的一個復(fù)本,b 持有它的另一個復(fù) 本。b 更改時,a 的值保持不變。
c 和 d 則分別指向同一個復(fù)合值 [1,2,3] 的兩個不同引用。請注意,c 和 d 僅僅是指向值 [1,2,3],并非持有。所以它們更改的是同一個值(如調(diào)用 .push(4)),隨后它們都指向更 改后的新值 [1,2,3,4]。
由于引用指向的是值本身而非變量,所以一個引用無法更改另一個引用的指向。
b=[4,5,6] 并不影響 a 指向值 [1,2,3],除非 b 不是指向數(shù)組的引用,而是指向 a 的指針, 但在 JavaScript 中不存在這種情況!
函數(shù)參數(shù)就經(jīng)常讓人產(chǎn)生這樣的困惑:
我們向函數(shù)傳遞 a 的時候,實際是將引用 a 的一個復(fù)本賦值給 x,而 a 仍然指向 [1,2,3]。 在函數(shù)中我們可以通過引用 x 來更改數(shù)組的值(push(4) 之后變?yōu)?[1,2,3,4])。但 x = [4,5,6] 并不影響 a 的指向,所以 a 仍然指向 [1,2,3,4]。
我們不能通過引用 x 來更改引用 a 的指向,只能更改 a 和 x 共同指向的值。
如果要將 a 的值變?yōu)?[4,5,6,7],必須更改 x 指向的數(shù)組,而不是為 x 賦值一個新的數(shù)組。
從上例可以看出,x.length = 0 和 x.push(4,5,6,7) 并沒有創(chuàng)建一個新的數(shù)組,而是更改 了當(dāng)前的數(shù)組。于是 a 指向的值變成了 [4,5,6,7]。
請記住:我們無法自行決定使用值復(fù)制還是引用復(fù)制,一切由值的類型來決定。
如果通過值復(fù)制的方式來傳遞復(fù)合值(如數(shù)組),就需要為其創(chuàng)建一個復(fù)本,這樣傳遞的 就不再是原始值。例如:
foo( a.slice() );
slice(..) 不帶參數(shù)會返回當(dāng)前數(shù)組的一個淺復(fù)本(shallow copy)。由于傳遞給函數(shù)的是指 向該復(fù)本的引用,所以 foo(..) 中的操作不會影響 a 指向的數(shù)組。
相反,如果要將標量基本類型值傳遞到函數(shù)內(nèi)并進行更改,就需要將該值封裝到一個復(fù)合 值(對象、數(shù)組等)中,然后通過引用復(fù)制的方式傳遞。
這里 obj 是一個封裝了標量基本類型值 a 的封裝對象。obj 引用的一個復(fù)本作為參數(shù) wrapper 被傳遞到 foo(..) 中。這樣我們就可以通過 wrapper 來訪問該對象并更改它的屬 性。函數(shù)執(zhí)行結(jié)束后 obj.a 將變成 42。
這樣看來,如果需要傳遞指向標量基本類型值的引用,就可以將其封裝到對應(yīng) 的數(shù)字封裝對象中。
與預(yù)期不同的是,雖然傳遞的是指向數(shù)字對象的引用復(fù)本,但我們并不能通過它來更改其 中的基本類型值:
原因是標量基本類型值是不可更改的(字符串和布爾也是如此)。如果一個數(shù)字對象的標 量基本類型值是 2,那么該值就不能更改,除非創(chuàng)建一個包含新值的數(shù)字對象。
x = x + 1 中,x 中的標量基本類型值 2 從數(shù)字對象中拆封(或者提取)出來后,x 就神不 知鬼不覺地從引用變成了數(shù)字對象,它的值為 2 + 1 等于 3。然而函數(shù)外的 b 仍然指向原 來那個值為 2 的數(shù)字對象。
相對而言,前面用 obj 作為封裝對象的辦法可能更好一些。這并不是說數(shù)字等封裝對象沒 有什么用,只是多數(shù)情況下我們應(yīng)該優(yōu)先考慮使用標量基本類型。
引用的功能很強大,但有時也難免成為阻礙。賦值 / 參數(shù)傳遞是通過引用還是值復(fù)制完全 由值的類型來決定,所以使用哪種類型也間接決定了賦值 / 參數(shù)傳遞的方式。
總結(jié)
以上是生活随笔為你收集整理的引用js_js值和引用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZedGraph使用经验
- 下一篇: 《31个工作习惯》