摘要:關(guān)于的求值策略,問中函數(shù)的參數(shù)傳遞是按值傳遞還是按引用傳遞回答很經(jīng)典。所以不能說中函數(shù)的參數(shù)傳遞嚴(yán)格按值傳遞或按引入傳遞。中還采用一種參數(shù)傳遞策略,叫按共享傳遞。中參數(shù)是必須先求值再作為實參傳入函數(shù)的。參考求值策略中函數(shù)參數(shù)的默認(rèn)值
最近在研究 lambda 演算中的 η-變換 在 JavaScript 中的應(yīng)用,偶然在 stackoverflow 上看到一個比較有意思的問題。關(guān)于 JavaScript 的求值策略,問JS中函數(shù)的參數(shù)傳遞是按值傳遞還是按引用傳遞?回答很經(jīng)典。
一栗以蔽之function changeStuff(a, b, c) { a = a * 10; b.item = "changed"; c = {item: "changed"}; } var num = 10; var obj1 = {item: "unchanged"}; var obj2 = {item: "unchanged"}; changeStuff(num, obj1, obj2); console.log(num); // 10 console.log(obj1.item); // changed console.log(obj2.item); // unchanged
如果說JS中函數(shù)的參數(shù)傳遞是按值傳遞,那么在函數(shù)changeStuff內(nèi)部改變b.item的值將不會影響外部的obj1對象的值。
如果說JS中函數(shù)的參數(shù)傳遞是按引入傳遞,那函數(shù)changeStuff內(nèi)部所做的改變將會影響到函數(shù)外部所有的變量定義,num將會變成100、obj2.item將會變成changed。很顯然實際不是這樣子的。
所以不能說JS中函數(shù)的參數(shù)傳遞嚴(yán)格按值傳遞或按引入傳遞。總的來說函數(shù)的參數(shù)都是按值傳遞的。JS中還采用一種參數(shù)傳遞策略,叫按共享傳遞。這要取決于參數(shù)的類型。
如果參數(shù)是基本類型,那么是按值傳遞的;
如果參數(shù)是引用類型,那么是按共享傳遞的。
參數(shù)傳遞ECMAScript 中所有函數(shù)的參數(shù)都是按值傳遞的。也就是說,把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就和把值從一個變量復(fù)制到另一個變量一樣。基本類型值的傳遞如同基本類型變量的復(fù)制一樣,而引用類型值的傳遞,則如同引用類型變量的復(fù)制一樣。-- 《JavaScript高級程序設(shè)計》
紅寶書上講所有函數(shù)的參數(shù)都是按值傳遞的,到底是不是呢?讓我們分析下上面的栗子:
按值傳遞JavaScript中基本類型作為參數(shù)的策略為 按值傳遞(call by value):
function foo(a) { a = a * 10; } var num = 10; foo(num); console.log(num); // 10 沒有變化
這里看到函數(shù)內(nèi)部參數(shù)的改變并沒有影響到外部變量。按值傳遞沒錯。
按共享傳遞JavaScript中對象作為參數(shù)傳遞的策略為 按共享傳遞(call by sharing):
修改參數(shù)的屬性將會影響到外部對象
重新賦值將不會影響到外部對象
按上面栗子函數(shù)內(nèi)部修改了參數(shù)b的屬性item,會影響到函數(shù)外部對象,因而obj1的屬性item也變了。
function bar(b) { b.item = "changed"; console.log(b === obj1) // true } var obj1 = {item: "unchanged"}; bar(obj1); console.log(obj1.item); // changed 修改參數(shù)的屬性將會影響到外部對象
從b === obj1打印結(jié)果為true可以看出,函數(shù)內(nèi)部修改了參數(shù)的屬性并沒有影響到參數(shù)的引用。b和obj1共享一個對象地址,所以修改參數(shù)的屬性將會影響到外部對象。
而將參數(shù)c重新賦值一個新對象,將不會影響到外部對象。
function baz(c) { c = {item: "changed"}; console.log(c === obj2) // false } var obj2 = {item: "unchanged"}; baz(obj2); console.log(obj2.item); // unchanged 重新賦值將不會影響到外部對象
將參數(shù)c重新賦值一個新對象,那么c就綁定到了一個新的對象地址,c === obj2打印結(jié)果為false,判斷他們不再共享同一個對象地址。它們各自有獨立的對象地址。所以重新賦值將不會影響到外部對象。
總結(jié)可以說 按共享傳遞 是 按值傳遞 的特例,傳遞的是引用地址的拷貝。所以紅寶書上說的也沒錯。
可以把 ECMAScript 函數(shù)的參數(shù)想象成局部變量。-- 《JavaScript高級程序設(shè)計》延伸 - 惰性求值
前面了解到了所有函數(shù)的參數(shù)都是按值傳遞的。JavaScript 中參數(shù)是必須先求值再作為實參傳入函數(shù)的。但是在ES6中有一個特例。
參數(shù)默認(rèn)值不是傳值的,而是每次都重新計算默認(rèn)值表達(dá)式的值。也就是說,參數(shù)默認(rèn)值是惰性求值的。 -- 《ECMAScript 6 入門》
let x = 99; function foo(p = x + 1) { console.log(p); } foo() // 100 x = 100; foo() // 101
上面代碼中,參數(shù)p的默認(rèn)值是x + 1。這時,每次調(diào)用函數(shù)foo,都會重新計算x + 1,而不是默認(rèn)p等于 100。
參考求值策略
Is JavaScript a pass-by-reference or pass-by-value language?
ES6 中函數(shù)參數(shù)的默認(rèn)值
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92452.html
摘要:我將這個策略稱之為閑置直到緊急。請注意,在腳本執(zhí)行時,它作為單個任務(wù)需要毫秒才能運行完成。很明顯,解決方案是將這些代碼分解為多個任務(wù)。原因如下推遲組件初始化僅在組件尚未渲染時才有用。這稱為輸入優(yōu)先級。 showImg(https://img.alicdn.com/tfs/TB1u.rsepzqK1RjSZFzXXXjrpXa-1919-913.png); Idle Until Urge...
摘要:按引用傳遞時,函數(shù)的形參接收實參的隱式引用,而不再是副本。探究值的傳遞方式的基本類型,是按值傳遞的。但這樣是否說明的對象是按引用傳遞的呢我們再看下面的例子仍然是并未被修改為如果是按引用傳遞,修改形參的值,應(yīng)該影響到實參才對。 最近遇到個有趣的問題:JS中的值是按值傳遞,還是按引用傳遞呢? 在分析這個問題之前,我們需了解什么是按值傳遞(call by value),什么是按引用傳遞(ca...
摘要:在開始解析之前,先通過詞法分析器運行源碼,這會將源碼打散成語法中全大寫的部分。我們基于每個規(guī)則的名稱的左側(cè)為其創(chuàng)建一個方法,再來看右側(cè)內(nèi)容如果是全大寫的單詞,說明它是一個終止符即一個,詞法分析器會用到它。 本文轉(zhuǎn)載自:眾成翻譯譯者:文藺鏈接:http://www.zcfy.cc/article/661原文:http://tadeuzagallo.com/blog/writing-a-l...
摘要:來源編程精解中文第三版翻譯項目原文譯者飛龍協(xié)議自豪地采用谷歌翻譯部分參考了編程精解第版確定編程語言中的表達(dá)式含義的求值器只是另一個程序。若文本不是一個合法程序,解析器應(yīng)該指出錯誤。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Project: A Programming Language 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用...
摘要:每個候選項都是大括號中的語句序列。短路運算符有一個很重要的功能它們并不真的需要布爾值操作數(shù),注意換句話說,不會將數(shù)字轉(zhuǎn)換為布爾值。練習(xí)對表達(dá)式求值。首先對求值,轉(zhuǎn)換為繼續(xù)對右邊表達(dá)式求值,為,造成短路,不對進(jìn)行計算,返回對表達(dá)式求值。 4.1 聲明語句 聲明語句也叫變量語句,這種語句會創(chuàng)建新變量??梢栽诼暶髯兞繒r給出初始值,如果沒有明確給出,變量的值就是undefined。 ...
閱讀 1598·2023-04-26 02:43
閱讀 2994·2021-11-11 16:54
閱讀 1344·2021-09-23 11:54
閱讀 1165·2021-09-23 11:22
閱讀 2359·2021-08-23 09:45
閱讀 845·2019-08-30 15:54
閱讀 3094·2019-08-30 15:53
閱讀 3184·2019-08-30 15:53