檢查這個fiddle或下面的代碼沒有概念:在JavaScript超載
function abc(s) {
console.log('in abc(s)');
}
function abc(s, t) {
console.log('in abc(s,t)');
}
abc('1');
這個問題的輸出總是in abc(s,t)
是否有人可以給我解釋一下什麼在這裏,爲什麼回事?
檢查這個fiddle或下面的代碼沒有概念:在JavaScript超載
function abc(s) {
console.log('in abc(s)');
}
function abc(s, t) {
console.log('in abc(s,t)');
}
abc('1');
這個問題的輸出總是in abc(s,t)
是否有人可以給我解釋一下什麼在這裏,爲什麼回事?
首先,JavaScript中沒有方法重載支持(請參閱@ 6502 workaround)。
其次,描述您遇到什麼,在JavaScript中,最後聲明的函數(與相同名)被調用,因爲前者已被覆蓋,它涉及到JavaScript Hoisting。
再次嘗試重新排序函數的聲明,看看輸出結果:
function abc(s, t) {
console.log('in abc(s,t)');
}
function abc(s) {
console.log('in abc(s)');
}
abc('1');
在Javascript中沒有超載的概念。
然而,您可以編寫一個函數,通過使用arguments
值來檢查已傳遞多少個參數。
function foo(s, t) {
if (arguments.length == 2) {
...
} else {
...
}
}
所有參數的函數簽名預期但沒有被接收爲undefined
傳遞給調用者。您也可以通過簡單訪問與arguments[i]
傳遞的第n個參數來編寫可變參數函數。但請注意,arguments
不是Javascript數組,因此並非所有數組方法都可用。
關於能夠多次重新定義同一個函數而沒有錯誤因爲規則很奇怪,所以解釋起來有點複雜。
一個簡單的解釋是你可以想到的是function
是一個可執行語句,就像它在Python中一樣,所以最後一個函數定義獲勝。然而,因爲不同於Python的,下面是合法的Javascript代碼,這將是錯誤的:
console.log(square(12));
function square(x) { return x*x; }
即你可以調用一個函數在被定義之前(在腳本行:當然輸入這兩條線一個Javascript控制檯不會工作)。
稍微更正確的解釋是編譯器首先解析所有函數定義(最後的勝利)然後開始執行代碼。如果你沒有把function
放在if
裏面,這個心理模型就可以工作,因爲在這種情況下實際發生的事情是依賴於實現的(並且我不是在談論瘋狂的IE,但即使是FF和Chrome也會做不同的事情)。只是不要那樣做。
你甚至可以使用的形式
var square = function(x) { return x*x; }
在這種情況下它的時候通過它的流時執行的「函數式」的變量的簡單任務(所以這是確定放置不同函數在不同的if
分支中的實現,但在分配實現之前無法調用該函數)。
注意事項:雖然這是真的,你不能'arguments.forEach(func)',你仍然可以做'[] .forEach.call(arguments,func)' –
在javascript中,只有一個具有任何給定名稱的函數,並且如果聲明具有相同名稱的多個函數,則聲明的最後一個函數將是活動的函數。
但是,您可以測試傳遞給您的函數的參數,並實現函數重載旨在處理的許多相同類型的行爲。事實上,在某些情況下,你可以做更多。
在你的具體的例子:
function abc(s, t) {
// test to see if the t argument was passed
if (t !== undefined) {
console.log('was called as abc(s,t)');
} else {
console.log('was called as abc(s)');
}
}
abc('1'); // outputs 'was called as abc(s)'
abc('1', '2'); // outputs 'was called as abc(s,t)'
但是,你還可以得到更多,更多創意(和有用)。
例如,jQuery .css()
方法可以被稱爲五種不同的方式。
.css(propertyName)
.css(propertyNames)
.css(propertyName, value)
.css(propertyName, function(index, value))
.css(properties)
.css()
所述方法中的代碼檢查的類型和自變量數目找出它被稱爲哪種方式,並且因此準確地進行什麼操作。
讓我們看看如何做才能找出其中5所形成這一功能正在被使用:
css: function(prop, value) {
// first figure out if we only have one argument
if (value === undefined) {
if (typeof prop === "string") {
// we have a simple request for a single css property by string name
// of this form: .css(propertyName)
} else if (Array.isArray(prop)) {
// we have a request for an array of properties
// of this form: .css(propertyNames)
} else if (typeof prop === "object") {
// property-value pairs of css to set
// of this form: .css(properties)
}
} else {
if (typeof value === "function") {
// of this form: .css(propertyName, function(index, value))
} else {
// of this form: .css(propertyName, value)
}
}
}
您還可以實現可選的參數。例如,jQuery的.hide()
可以接受許多形式。其中一種形式是.hide([duration ] [, complete ])
,其中持續時間和完成功能都是可選的。你可以傳遞任何東西,只是一個持續時間或持續時間和完成回調函數。這可以實現這樣的:
hide: function(duration, fn) {
// default the duration to zero if not present
duration = duration || 0;
// default the completion function to a dummy function if not present
fn = fn || function() {};
// now the code can proceed knowing that there are valid arguments for both
// duration and fn whether they were originally passed or not
}
我發現使用這些變量參數的最有效的方法之一是,允許代碼以支持各種不同的參數類型,但不管是什麼狀態你的論點進來,你可以通過他們,因爲你有他們,而不必將其轉換爲一些通用類型。例如,以JavaScript this implementation of a set object,所述.add()
方法可以利用這些不同形式的參數的所有:
s.add(key)
s.add(key1, key2, key3)
s.add([key1, key2, key3])
s.add(key1, [key8, key9], key2, [key4, key5])
s.add(otherSet) // any other set object
s.add(arrayLikeObject) // such as an HTMLCollection or nodeList
這兩者接受可變數量的參數,並且它接受多個不同類型的每個參數,它會根據傳遞給它的內容進行調整。因此,您可以通過鍵列表,鍵列數組,另一組鍵列,僞數組或任何這些類型的混合來初始化集合。在內部,代碼只是遍歷每個傳遞給函數的參數,檢查參數的類型並相應地執行。
您可以看到代碼here on GitHub瞭解更多信息。
發生什麼事是第二個函數聲明完全覆蓋了第一個函數聲明。爲什麼JS中沒有重載這樣的概念。 – m90
定義的最新函數覆蓋符號表中的前一個函數 – thefourtheye
那麼它總是調用它找到的最後一個函數? – SharpCoder