函數(shù)的組成
javascript(在下文中簡(jiǎn)稱(chēng)為js)中函數(shù)是一等公民咆耿。
函數(shù)的組成分為:函數(shù)名杆煞,函數(shù)執(zhí)行語(yǔ)句體娩嚼,參數(shù)三部分組成蘑险,當(dāng)然函數(shù)的參數(shù)相對(duì)于函數(shù)來(lái)說(shuō)是可以存在的,也可以不存在岳悟。這里就不賣(mài)關(guān)子了佃迄。
函數(shù)的參數(shù)
現(xiàn)在主要討論的就是函數(shù)的參數(shù)問(wèn)題。函數(shù)的參數(shù)我們大致分為:實(shí)參與形參贵少。
????1.實(shí)參:可以粗略的理解成當(dāng)在調(diào)用函數(shù)時(shí)候需要向函數(shù)執(zhí)行體中傳入的指令呵俏。
????2.形參:可以理解成函數(shù)在定義時(shí),需要接受到相關(guān)的指令來(lái)執(zhí)行函數(shù)體語(yǔ)句的實(shí)參指令的占位符滔灶。
函數(shù)定義參數(shù)與傳入的參數(shù)差異問(wèn)題
????在js中普碎,允許函數(shù)定義參數(shù)與傳入的參數(shù)的數(shù)量不一致(這也是js靈活的地方與操蛋的地方)。我們知道當(dāng)傳參與定義參不一致的時(shí)候宽气,我們就會(huì)考慮參數(shù)定義的順序随常、參數(shù)的類(lèi)型、參數(shù)的默認(rèn)值萄涯,參數(shù)是否接受到值等一系列問(wèn)題绪氛。
????在ES5至以前,我們對(duì)于不定數(shù)目的參數(shù)涝影,使用?arguments?這個(gè)類(lèi)數(shù)組(具有l(wèi)ength屬性的對(duì)象)來(lái)統(tǒng)一接收函數(shù)調(diào)用時(shí)所傳入的所有參數(shù)枣察。請(qǐng)看下面例子:
? ? 輸出的結(jié)果:
????很顯然 argument 是不管在函數(shù)中是否有定義形參,全部接收在函數(shù)調(diào)用處傳入進(jìn)來(lái)的實(shí)參。
ES6對(duì)arguments的改變
? ? 在函數(shù)的定義過(guò)程中序目,是有可能改變形參的值情況出現(xiàn)臂痕。當(dāng)在函數(shù)執(zhí)行體中,我們先改變了形參的值猿涨,然后使用 arguments 來(lái)讀取傳入的實(shí)參握童。
輸出的結(jié)果為:
? ? 很顯然的就能看出形參的值在函數(shù)執(zhí)行體中被改變了,arguments的值也會(huì)被改變叛赚。這樣在函數(shù)形參值改變之后獲取arguments的值是不準(zhǔn)確的澡绩。因此在es6中不建議使用arguments來(lái)獲取接收不定數(shù)目的參數(shù)。
擴(kuò)展運(yùn)算符(...)對(duì)函數(shù)不定參數(shù)的影響
? ? 上面說(shuō)到在es6之后不建議使用arguments來(lái)進(jìn)行不定參數(shù)的接收之后俺附,應(yīng)該使用怎么樣的一種方式來(lái)接收不定參數(shù)較為妥當(dāng)肥卡?
? ? 在 es6中使用擴(kuò)展運(yùn)算符(...)來(lái)替代arguments對(duì)不定參數(shù)的接收。
? ? 擴(kuò)展運(yùn)算符(...):可以理解成一個(gè)默認(rèn)的遍歷器(本章節(jié)只討論擴(kuò)展運(yùn)算符對(duì)函數(shù)參數(shù)上的應(yīng)用)事镣。
輸出結(jié)果為:
從輸出的結(jié)果可以看出擴(kuò)展運(yùn)算符會(huì)把函數(shù)調(diào)用傳入的參數(shù)封裝到一個(gè)數(shù)組中輸出步鉴。
在函數(shù)體語(yǔ)句中我們可以改變...arg的值:
輸出結(jié)果為:
? ? 這樣就能夠清晰的通過(guò)一個(gè)顯示的變量來(lái)接收所有的不定數(shù)目的參數(shù)璃哟。避免在形參值改變之后使用argments來(lái)獲取傳入的實(shí)參值氛琢。
函數(shù)參數(shù)的默認(rèn)值
? ? 在定義函數(shù)時(shí),通常會(huì)給定形參一個(gè)默認(rèn)值沮稚,以便當(dāng)不傳實(shí)參時(shí)艺沼,使用默認(rèn)值來(lái)進(jìn)行替代。現(xiàn)在主要說(shuō)的是ES6中的默認(rèn)參數(shù)值蕴掏。
輸出的結(jié)果為:
明顯的看出當(dāng)不傳參數(shù)的時(shí)候使用的是默認(rèn)值中的值障般。
????那么問(wèn)題來(lái)了,一般在定義函數(shù)參數(shù)的使用盛杰,不可能把所有的默認(rèn)參都放在最后面挽荡,因?yàn)樵谇懊娑继岬竭^(guò)函數(shù)的傳入?yún)?shù)和接收參數(shù)是可以數(shù)目不一致的。在下面的例子中即供,我們應(yīng)該如何獲取到默認(rèn)值定拟?
? ? 說(shuō)到這里了一定會(huì)有人說(shuō),直接調(diào)用foo()就可以獲取到a的默認(rèn)值了逗嫡。如果你是這樣想青自,你就沒(méi)有考慮清除,當(dāng)然這么做是對(duì)的驱证,因?yàn)槭纠@樣執(zhí)行是能夠得到默認(rèn)值這個(gè)答案的延窜。
? ? 稍微得把代碼改變一下,你看使用foo()來(lái)執(zhí)行是否可以抹锄?
當(dāng)然這樣執(zhí)行是不報(bào)錯(cuò)的逆瑞,但是結(jié)果是這樣的荠藤,得不到a的值。這就更加沒(méi)辦法輸出a的值了获高,更加談不上獲取默認(rèn)值哈肖。
針對(duì)上面的情況,接下來(lái)就是一個(gè)從來(lái)都在被輕視而且特別重要的問(wèn)題出現(xiàn)了念秧?什么問(wèn)題呢淤井?請(qǐng)看下面的大標(biāo)題。
函數(shù)參數(shù)的優(yōu)先級(jí)
? ? 都聽(tīng)說(shuō)過(guò)運(yùn)算符的優(yōu)先級(jí)出爹,js中this的優(yōu)先級(jí)∽穑現(xiàn)在來(lái)了一個(gè)新的概念:函數(shù)參數(shù)的優(yōu)先級(jí)。
? ? 針對(duì)上面輸出函數(shù)參數(shù)默認(rèn)值的問(wèn)題严就,在這個(gè)時(shí)候就可以解決了。
? ? 函數(shù)參數(shù)的優(yōu)先級(jí):是針對(duì)函數(shù)調(diào)用時(shí)候的傳入實(shí)參的優(yōu)先級(jí)比較器罐,不是針對(duì)形參的梢为。
? ? 現(xiàn)在我們來(lái)改寫(xiě)一下,上面出現(xiàn)問(wèn)題中的函數(shù)調(diào)用就可以獲取到a的默認(rèn)值轰坊,如下所示:
????把需要獲取默認(rèn)值的形參對(duì)應(yīng)的實(shí)參使用undefined來(lái)進(jìn)行傳入的時(shí)候铸董,我們突然發(fā)現(xiàn)。居然可以輸出 a = 1肴沫。
? ? 是不是覺(jué)得特別神奇粟害。當(dāng)初我也是這么覺(jué)得的。
? ? 說(shuō)到這里颤芬,發(fā)現(xiàn)可以使用undefined 來(lái)進(jìn)行占位悲幅,讓函數(shù)輸出其默認(rèn)值。腦袋里會(huì)順勢(shì)想到使用null是不是也可以站蝠。很顯然猜測(cè)是最沒(méi)有底氣的√撸現(xiàn)在我們實(shí)際調(diào)用來(lái)看看。
? ? 輸出的結(jié)果為:
? ? 很顯然菱魔,不能得到a的默認(rèn)值留荔。
? ? 接下來(lái)我們使用比較特殊的NaN來(lái)嘗試一下。直接上代碼:
? ? 輸出的結(jié)果為:
? ? NaN很顯然也會(huì)覆蓋掉默認(rèn)值澜倦。
? ? 至于一般的數(shù)據(jù)類(lèi)型(string聚蝶,number,? boolean, object)等類(lèi)型希望大家去嘗試一下,是否能夠覆蓋藻治,在這里我就不一一的描述碘勉。
? ? 優(yōu)先級(jí)總結(jié):從上面的例子中,發(fā)現(xiàn)undefined不能覆蓋參數(shù)默認(rèn)值栋艳,null和NaN都能去覆蓋參數(shù)默認(rèn)值恰聘,可以得出函數(shù)參數(shù)的優(yōu)先級(jí):undefined < 默認(rèn)參 < 除undefined以外的實(shí)參?(NaN /?null)。
? ? 如有不足,歡迎各位大神指正晴叨!
? ? 原創(chuàng)文章轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/52f26809ceb4