深入學(xué)習(xí)JavaScript中的Rest參數(shù)和參數(shù)默認(rèn)值
本文將討論使 JavaScript 函數(shù)更有表現(xiàn)力的兩個(gè)特性:Rest 參數(shù)和參數(shù)默認(rèn)值。
Rest 參數(shù)
通常,我們需要?jiǎng)?chuàng)建一個(gè)可變參數(shù)的函數(shù),可變參數(shù)是指函數(shù)可以接受任意數(shù)量的參數(shù)。例如,String.prototype.concat 可以接受任何數(shù)量的字符串作為參數(shù)。使用 Rest 參數(shù),ES6 為我們提供一種新的方式來(lái)創(chuàng)建可變參數(shù)的函數(shù)。
我們來(lái)實(shí)現(xiàn)一個(gè)示例函數(shù) containsAll,用于檢查一個(gè)字符串中是否包含某些子字符串。例如,containsAll("banana", "b", "nan") 將返回true,containsAll("banana", "c", "nan") 將返回 false。
下面是傳統(tǒng)的實(shí)現(xiàn)方式:
function containsAll(haystack) { for (var i = 1; i < arguments.length; i++) { var needle = arguments[i]; if (haystack.indexOf(needle) === -1) { return false; } } return true; } function containsAll(haystack) { for (var i = 1; i < arguments.length; i++) { var needle = arguments[i]; if (haystack.indexOf(needle) === -1) { return false; } } return true; }
該實(shí)現(xiàn)用到了 arguments 對(duì)象,該對(duì)象是一個(gè)類(lèi)數(shù)組對(duì)象,包含函數(shù)被調(diào)用時(shí)的實(shí)參列表。這段代碼正是我們想要的,但其可讀性卻不是最優(yōu)的。函數(shù)只有一個(gè)形參 haystack,所以不可能一看就知道該函數(shù)需要多個(gè)參數(shù),并且在遍歷 arguments 時(shí),需要特別注意遍歷的開(kāi)始索引為1 ,而不是常見(jiàn)的 0,因?yàn)?arguments[0] 就是函數(shù)定義時(shí)的形參 haystack。如果我們想在 haystack 參數(shù)之前或之后添加一些參數(shù),我們不得不更新內(nèi)部的循環(huán)。Rest 參數(shù)解決了這些問(wèn)題,下面是 使用 Rest 參數(shù)的實(shí)現(xiàn)方式:
function containsAll(haystack, ...needles) { for (var needle of needles) { if (haystack.indexOf(needle) === -1) { return false; } } return true; } function containsAll(haystack, ...needles) { for (var needle of needles) { if (haystack.indexOf(needle) === -1) { return false; } } return true; }
以上兩個(gè)實(shí)現(xiàn)都滿(mǎn)足了我們的需求,但后者包含一個(gè)特殊的 ...needles 語(yǔ)法。我們來(lái)看看調(diào)用containsAll("banana", "b", "nan") 時(shí)的細(xì)節(jié),參數(shù) haystack 和以往一樣,將用函數(shù)的第一個(gè)實(shí)參填充,值為 "banana",needles 前面的省略號(hào)表示它是一個(gè) Rest 參數(shù),剩余的所有實(shí)參將被放入一個(gè)數(shù)組中,并將該數(shù)組賦給 needles 遍量。在這個(gè)調(diào)用中,needles 的值為 ["b", "nan"]。然后,就是正常的函數(shù)執(zhí)行了。
只能將函數(shù)的最后一個(gè)函數(shù)作為 Rest 參數(shù),在函數(shù)被調(diào)用時(shí),Rest 參數(shù)之前的參數(shù)都將被正常填充,之外的參數(shù)將被放入一個(gè)數(shù)組中,并將該數(shù)組作為 Rest 參數(shù)的值,如果沒(méi)有更多的參數(shù),那么 Rest 參數(shù)的值為一個(gè)空數(shù)組 [],Rest 參數(shù)的值永遠(yuǎn)都不會(huì)是 undefined。
參數(shù)的默認(rèn)值
通常,調(diào)用一個(gè)函數(shù)時(shí),不需要調(diào)用者傳遞所有可能的參數(shù),那些沒(méi)有傳遞的參數(shù)都需要一個(gè)合理的默認(rèn)值。JavaScript 對(duì)那些沒(méi)有傳遞的參數(shù)都有一個(gè)固定的默認(rèn)值 undefined。在 ES6 中,引入了一種新方法來(lái)指定任意參數(shù)的默認(rèn)值。
看下面例子:
function animalSentence(animals2="tigers", animals3="bears") { return `Lions and ${animals2} and ${animals3}! Oh my!`; } function animalSentence(animals2="tigers", animals3="bears") { return `Lions and ${animals2} and ${animals3}! Oh my!`; }
在每個(gè)參數(shù)的 = 后面是一個(gè)表達(dá)式,指定了參數(shù)未傳遞時(shí)的默認(rèn)值。所以,animalSentence() 返回 "Lions and tigers and bears! Oh my!", animalSentence("elephants") 返回"Lions and elephants and bears! Oh my!", animalSentence("elephants", "whales") 返回 "Lions and elephants and whales! Oh my!"。
參數(shù)默認(rèn)值需要注意的幾個(gè)細(xì)節(jié):
與 Python 不一樣的是,參數(shù)默認(rèn)值的表達(dá)式是在函數(shù)調(diào)用時(shí)從左到右計(jì)算的,這意味著表達(dá)式可以使用前面已經(jīng)被填充的參數(shù)。例如,我們可以將上面的函數(shù)變得更有趣一點(diǎn):
function animalSentenceFancy(animals2="tigers", animals3=(animals2 == "bears") ? "sealions" : "bears") { return `Lions and ${animals2} and ${animals3}! Oh my!`; } function animalSentenceFancy(animals2="tigers", animals3=(animals2 == "bears") ? "sealions" : "bears") { return `Lions and ${animals2} and ${animals3}! Oh my!`; }
那么,animalSentenceFancy("bears") 將返回 "Lions and bears and sealions. Oh my!"。
傳遞 undefined 等同于沒(méi)有傳遞該參數(shù)。因此,animalSentence(undefined, "unicorns") 將返回 "Lions and tigers and unicorns! Oh my!"。
如果沒(méi)有為一個(gè)參數(shù)指定默認(rèn)值,那么該參數(shù)的默認(rèn)值為 undefined,所以
function myFunc(a=42, b) {...} function myFunc(a=42, b) {...}
等同于
function myFunc(a=42, b=undefined) {...} function myFunc(a=42, b=undefined) {...}
拋棄 arguments
通過(guò) Rest 參數(shù)和參數(shù)的默認(rèn)值,我們可以完全拋棄 arguments 對(duì)象,使我們的代碼可讀性更高。此外,arguments 對(duì)象也加深了優(yōu)化 JavaScript 的難題。
希望以上兩個(gè)新特性可以完全取代 arguments。作為第一步,在使用 Rest 參數(shù)或參數(shù)的默認(rèn)值時(shí),請(qǐng)避免使用 arguments 對(duì)象,假如 arguments 對(duì)象還不會(huì)立即被移除,或者永遠(yuǎn)不會(huì),那么也最好是避免在使用 Rest 參數(shù)或參數(shù)默認(rèn)值時(shí)使用 arguments 對(duì)象。
兼容性
Firefox 15 以上的版本已經(jīng)支持這兩個(gè)新特性。然而,除此之外,還沒(méi)有其他任何瀏覽器支持。最近,V8 的實(shí)驗(yàn)環(huán)境添加了對(duì) Rest 參數(shù)的支持,而參數(shù)默認(rèn)值還有一個(gè) issue,JSC 也對(duì) Rest 參數(shù)和參數(shù)默認(rèn)值提了一些 issue。
Babel 和 Traceur 這兩個(gè)編譯器都已經(jīng)支持了參數(shù)默認(rèn)值,所以你可以大膽使用。
結(jié)論
盡管從技術(shù)層面上看,這兩個(gè)新特性在并沒(méi)有給函數(shù)引入新的行為,但它們可以使一些函數(shù)的聲明更具表現(xiàn)力和可讀性。
相關(guān)文章
WEB頁(yè)子窗口(showModalDialog和showModelessDialog)使用說(shuō)明
WEB頁(yè)子窗口(showModalDialog和showModelessDialog)使用說(shuō)明,大家可以看下。2009-10-10緩動(dòng)函數(shù)requestAnimationFrame 更好的實(shí)現(xiàn)瀏覽器經(jīng)動(dòng)畫(huà)
requestAnimationFrame是什么?一直是我們大家所疑惑的,緩動(dòng)函數(shù)requestAnimationFrame 更好的實(shí)現(xiàn)瀏覽器經(jīng)動(dòng)畫(huà),接下來(lái)將為大家詳細(xì)介紹2012-12-12javascript學(xué)習(xí)筆記(十四) window對(duì)象使用介紹
javascript學(xué)習(xí)筆記之window對(duì)象使用介紹,需要的朋友可以參考下2012-06-06javascript之Boolean類(lèi)型對(duì)象
本文主要介紹javascript中的Boolean類(lèi)型對(duì)象,Boolean對(duì)象非常簡(jiǎn)單,卻非常有用,希望能給大家做一個(gè)參考。2016-06-06關(guān)于js的三種使用方式(行內(nèi)js、內(nèi)部js、外部js)的程序代碼
本文主要和大家介紹關(guān)于js的三種使用方式(行內(nèi)js、內(nèi)部js、外部js)的實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家2018-05-05javascript學(xué)習(xí)筆記(十六) 系統(tǒng)對(duì)話框(alert、confirm、prompt)
javascript學(xué)習(xí)筆記之系統(tǒng)對(duì)話框(alert、confirm、prompt)使用介紹,學(xué)習(xí)js的朋友可以參考下2012-06-06