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