3 回答

TA貢獻(xiàn)2080條經(jīng)驗(yàn) 獲得超4個(gè)贊
Javascript中的參數(shù)重載有多個(gè)方面:
變量參數(shù) - 您可以傳遞不同的參數(shù)集(包括類(lèi)型和數(shù)量),并且函數(shù)的行為方式與傳遞給它的參數(shù)相匹配。
默認(rèn)參數(shù) - 如果參數(shù)未傳遞,則可以為參數(shù)定義默認(rèn)值。
命名參數(shù) - 參數(shù)順序變得無(wú)關(guān)緊要,您只需命名要傳遞給函數(shù)的參數(shù)。
以下是關(guān)于這些類(lèi)別的參數(shù)處理的每個(gè)部分。
變量參數(shù)
因?yàn)閖avascript沒(méi)有對(duì)參數(shù)或需要的參數(shù)數(shù)量進(jìn)行類(lèi)型檢查,所以你可以myFunc()
通過(guò)檢查參數(shù)的類(lèi)型,存在或數(shù)量來(lái)實(shí)現(xiàn)一個(gè)可以適應(yīng)傳遞給它的參數(shù)的實(shí)現(xiàn)。
jQuery一直這樣做。您可以將某些參數(shù)設(shè)置為可選,也可以根據(jù)傳遞給它的參數(shù)在函數(shù)中進(jìn)行分支。
在實(shí)現(xiàn)這些類(lèi)型的重載時(shí),您可以使用幾種不同的技術(shù):
您可以通過(guò)檢查聲明的參數(shù)名稱(chēng)值是否為,來(lái)檢查是否存在任何給定的參數(shù)
undefined
。您可以查看總數(shù)量或參數(shù)
arguments.length
。您可以檢查任何給定參數(shù)的類(lèi)型。
對(duì)于可變數(shù)量的參數(shù),您可以使用
arguments
偽數(shù)組來(lái)訪(fǎng)問(wèn)任何給定的參數(shù)arguments[i]
。
這里有些例子:
我們來(lái)看看jQuery的obj.data()
方法。它支持四種不同的使用形式:
obj.data("key");obj.data("key", value);obj.data();obj.data(object);
每一個(gè)觸發(fā)一個(gè)不同的行為,并且不使用這種動(dòng)態(tài)形式的重載,將需要四個(gè)單獨(dú)的功能。
以下是用英語(yǔ)辨別所有這些選項(xiàng)的方法,然后我將它們?nèi)亢喜⒌酱a中:
// get the data element associated with a particular key valueobj.data("key");
如果傳遞給的第一個(gè)參數(shù).data()
是一個(gè)字符串而第二個(gè)參數(shù)是undefined
,則調(diào)用者必須使用此表單。
// set the value associated with a particular keyobj.data("key", value);
如果第二個(gè)參數(shù)未定義,則設(shè)置特定鍵的值。
// get all keys/valuesobj.data();
如果沒(méi)有傳遞參數(shù),則返回返回對(duì)象中的所有鍵/值。
// set all keys/values from the passed in objectobj.data(object);
如果第一個(gè)參數(shù)的類(lèi)型是普通對(duì)象,則設(shè)置該對(duì)象的所有鍵/值。
以下是如何在一組javascript邏輯中組合所有這些:
// method declaration for .data() data: function(key, value) { if (arguments.length === 0) { // .data() // no args passed, return all keys/values in an object } else if (typeof key === "string") { // first arg is a string, look at type of second arg if (typeof value !== "undefined") { // .data("key", value) // set the value for a particular key } else { // .data("key") // retrieve a value for a key } } else if (typeof key === "object") { // .data(object) // set all key/value pairs from this object } else { // unsupported arguments passed } },
這種技術(shù)的關(guān)鍵是確保您想要接受的所有形式的參數(shù)都是唯一可識(shí)別的,并且從不會(huì)混淆調(diào)用者使用哪種形式。這通常需要對(duì)參數(shù)進(jìn)行適當(dāng)排序,并確保參數(shù)的類(lèi)型和位置有足夠的唯一性,您可以始終確定正在使用哪種形式。
例如,如果您有一個(gè)帶三個(gè)字符串參數(shù)的函數(shù):
obj.query("firstArg", "secondArg", "thirdArg");
您可以輕松地使第三個(gè)參數(shù)可選,您可以輕松地檢測(cè)到該條件,但您不能只使第二個(gè)參數(shù)可選,因?yàn)槟鸁o(wú)法分辨調(diào)用者的哪一個(gè)意味著要傳遞,因?yàn)闊o(wú)法確定是否第二個(gè)參數(shù)意味著是第二個(gè)參數(shù)或第二個(gè)參數(shù)被省略,所以第二個(gè)參數(shù)的位置實(shí)際上是第三個(gè)參數(shù):
obj.query("firstArg", "secondArg");obj.query("firstArg", "thirdArg");
由于所有三個(gè)參數(shù)都是相同的類(lèi)型,因此您無(wú)法區(qū)分不同的參數(shù),因此您不知道調(diào)用者的意圖。使用此調(diào)用樣式,只有第三個(gè)參數(shù)可以是可選的。如果你想省略第二個(gè)參數(shù),它必須作為null
(或其他一些可檢測(cè)的值)傳遞,你的代碼會(huì)檢測(cè)到:
obj.query("firstArg", null, "thirdArg");
這是一個(gè)可選參數(shù)的jQuery示例。兩個(gè)參數(shù)都是可選的,如果沒(méi)有傳遞則采用默認(rèn)值:
clone: function( dataAndEvents, deepDataAndEvents ) { dataAndEvents = dataAndEvents == null ? false : dataAndEvents; deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; return this.map( function () { return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); });},
這是一個(gè)jQuery示例,其中參數(shù)可以丟失,或者三種不同類(lèi)型中的任何一種,它們?yōu)槟峁┝怂姆N不同的重載:
html: function( value ) { if ( value === undefined ) { return this[0] && this[0].nodeType === 1 ? this[0].innerHTML.replace(rinlinejQuery, "") : null; // See if we can take a shortcut and just use innerHTML } else if ( typeof value === "string" && !rnoInnerhtml.test( value ) && (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) && !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) { value = value.replace(rxhtmlTag, "<$1></$2>"); try { for ( var i = 0, l = this.length; i < l; i++ ) { // Remove element nodes and prevent memory leaks if ( this[i].nodeType === 1 ) { jQuery.cleanData( this[i].getElementsByTagName("*") ); this[i].innerHTML = value; } } // If using innerHTML throws an exception, use the fallback method } catch(e) { this.empty().append( value ); } } else if ( jQuery.isFunction( value ) ) { this.each(function(i){ var self = jQuery( this ); self.html( value.call(this, i, self.html()) ); }); } else { this.empty().append( value ); } return this;},
命名參數(shù)
其他語(yǔ)言(如Python)允許人們傳遞命名參數(shù)作為傳遞一些參數(shù)并使參數(shù)獨(dú)立于傳遞順序的方法.Javascript不直接支持命名參數(shù)的特性。通常在其位置使用的設(shè)計(jì)模式是傳遞屬性/值的映射。這可以通過(guò)傳遞具有屬性和值的對(duì)象來(lái)完成,或者在ES6及更高版本中,您實(shí)際上可以傳遞Map對(duì)象本身。
這是一個(gè)簡(jiǎn)單的ES5示例:
jQuery $.ajax()
接受一種用法,你只需要傳遞一個(gè)參數(shù),這是一個(gè)帶有屬性和值的常規(guī)Javascript對(duì)象。您傳遞的屬性確定將哪些參數(shù)/選項(xiàng)傳遞給ajax調(diào)用。有些可能是必需的,許多是可選的。由于它們是對(duì)象的屬性,因此沒(méi)有特定的順序。實(shí)際上,可以在該對(duì)象上傳遞30多個(gè)不同的屬性,只需要一個(gè)(url)。
這是一個(gè)例子:
$.ajax({url: "http://www.example.com/somepath", data: myArgs, dataType: "json"}).then(function(result) { // process result here});
在$.ajax()
實(shí)現(xiàn)內(nèi)部,它可以只詢(xún)問(wèn)傳入對(duì)象上傳遞的屬性并將其用作命名參數(shù)。這可以通過(guò)使用for (prop in obj)
或通過(guò)將所有屬性放入數(shù)組中Object.keys(obj)
然后迭代該數(shù)組來(lái)完成。
當(dāng)有大量參數(shù)和/或許多參數(shù)是可選的時(shí),這種技術(shù)在Javascript中非常常用。注意:這會(huì)對(duì)實(shí)現(xiàn)函數(shù)負(fù)責(zé),以確保存在最小有效參數(shù)集,并為調(diào)用者提供一些調(diào)試反饋,如果傳遞的參數(shù)不足則會(huì)丟失哪些內(nèi)容(可能通過(guò)拋出有用錯(cuò)誤消息的異常) 。
在ES6環(huán)境中,可以使用解構(gòu)來(lái)為上面?zhèn)鬟f的對(duì)象創(chuàng)建默認(rèn)屬性/值。這篇參考文章將對(duì)此進(jìn)行更詳細(xì)的討論。
這是該文章的一個(gè)例子:
function selectEntries({ start=0, end=-1, step=1 } = {}) { ···};
這將創(chuàng)建默認(rèn)屬性和值start
,end
并step
傳遞到一個(gè)對(duì)象的屬性selectEntries()
的功能。
函數(shù)參數(shù)的默認(rèn)值
在ES6中,Javascript為參數(shù)的默認(rèn)值添加了內(nèi)置語(yǔ)言支持。
例如:
function multiply(a, b = 1) { return a*b;}multiply(5); // 5
此處可以在MDN上使用此方法的進(jìn)一步說(shuō)明。

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超16個(gè)贊
嚴(yán)格意義上講,你不能做方法重載。不像它支持的方式java
或c#
。
問(wèn)題是JavaScript本身不支持方法重載。因此,如果它看到/解析兩個(gè)或多個(gè)具有相同名稱(chēng)的函數(shù),它將只考慮最后定義的函數(shù)并覆蓋之前的函數(shù)。
我認(rèn)為適合大多數(shù)情況的方式之一是 -
讓我們說(shuō)你有方法
function foo(x){}
您可以定義一個(gè)新方法,而不是在javascript中無(wú)法實(shí)現(xiàn)的重載方法
fooNew(x,y,z){}
然后修改第一個(gè)函數(shù)如下 -
function foo(x){ if(arguments.length==2) { return fooNew(arguments[0], arguments[1]); }}
如果您有許多這樣的重載方法,請(qǐng)考慮使用switch
而不僅僅是if-else
語(yǔ)句。
(更多細(xì)節(jié))PS:以上鏈接轉(zhuǎn)到我的個(gè)人博客,其中包含有關(guān)此內(nèi)容的其他詳細(xì)信息。
添加回答
舉報(bào)