詳解如何通過JavaScript實現(xiàn)函數(shù)重載
有的同學(xué)在開發(fā)中可能遇到過一個困擾,但是很少有人去解決這個問題,我這用一個例子展現(xiàn)出來
const searcher = {};
searcher.findAll = () => {
console.log("查詢所有用戶");
};
searcher.findByName = (name) => {
console.log("按照用戶名稱查詢");
};
searcher.findByFirstNameAndLastName = (firstName, lastName) => {
console.log("按照姓和名用戶查詢");
};可以看到上方的searcher對象有三個方法,但是他的查詢邏輯是不一樣。 findAll查詢所有用戶;findByName按照用戶名查;findByFirstNameAndLastName是按照姓和名查詢用戶,結(jié)構(gòu)上沒任何問題,那問題在哪?,惡心因為都是在做查詢,但又不得不給每一個函數(shù)取不同的名字,因為一旦重名就覆蓋了,如果說他們能取一樣的名字那該有多好
searcher.find = () => {
console.log("查詢所有用戶");
};
searcher.find = (name) => {
console.log("按照用戶名稱查詢");
};
searcher.find = (firstName, lastName) => {
console.log("按照姓和名用戶查詢");
};不傳參數(shù)就是查所有用戶
searcher.find()
給一個參數(shù)就是按照用戶名來查詢
searcher.find("aa")給兩個參數(shù)就是按照用戶的姓跟名來查詢
searcher.find("aa", "bb")
到用得時候也是非常的簡單,也符合邏邏輯,這個就叫做函數(shù)重載
函數(shù)重載:就是給函數(shù)取同一樣的一個函數(shù)名,根據(jù)你傳遞不同的參數(shù)數(shù)量,分別去調(diào)用不同的函數(shù)
好處:就在于使用不同的邏輯產(chǎn)生的函數(shù),給他們?nèi)∫粋€相同的名字,這樣在使用上我只需要記住這個一樣的名字就可以了,而不用去記這三個不同的名字,他有效的降低調(diào)用函數(shù)時產(chǎn)生的心智負(fù)擔(dān)。

但是JS不支持函數(shù)重載,所以說如果你寫成已上的形式,無論你怎么調(diào)用,一定是調(diào)用最后一個函數(shù),因為最后一個函數(shù)把前面的全部覆蓋了
不傳參數(shù)試一下,你看永遠(yuǎn)都是走最后一個函數(shù)的log
searcher.find() // 按照姓和名用戶查詢
那有什么辦法呢?在很早的時候jQuery之父John Resig 他就已經(jīng)提出了一個想法,我們能不能實現(xiàn)一個方法來幫助我們在js中完成函數(shù)重載?
于是他想出了一個addMethod方法,就是當(dāng)我要重載的時,我不直接去定義函數(shù),因為直接定義函數(shù)就會出現(xiàn)一個永遠(yuǎn)只調(diào)用最后一個函數(shù)的問題,而調(diào)用addMethod來定義函數(shù),把對象傳進(jìn)去,把函數(shù)的名字傳進(jìn)去,把函數(shù)的實現(xiàn)傳進(jìn)去,后面依次同理
addMethod(searcher, 'find', () => {
console.log('查詢所有用戶')
})
addMethod(searcher, 'find', (name) => {
console.log('按照用戶名稱查詢')
})
addMethod(searcher, 'find', (firstName, lastName) => {
console.log('按照姓和名用戶查詢')
})寫成這種格式之后,后面調(diào)用searcher.find()就能夠完成函數(shù)重載,問題是這個方法我們得要自己實現(xiàn),那么如何來實現(xiàn)? 這個方法他接受三個參數(shù),如果你不加處理的話你可能寫成下面函數(shù)一樣,給對象加一個屬性,這個屬性等于一個函數(shù),調(diào)用這個函數(shù)實際上就是在運行定義的實現(xiàn)函數(shù)fn,把this綁定帶過去 然后把傳遞過來的arguments帶過去
function addMethod(object, name, fn) {
object[name] = function () {
fn.apply(this, arguments)
}
}僅僅這么些還是搞不定,因為每次調(diào)用addMethod最后一次調(diào)用一定會把object里面同一個屬性給覆蓋掉,那么如何處理?看下方代碼
function addMethod(object, name, fn) {
const old = object[name];
object[name] = function () {
if (arguments.length === fn.length) {
fn.apply(this, arguments);
} else if (typeof old === "function") {
old.apply(this, arguments);
}
};
}首先我不傳參數(shù)走查詢所有用戶,傳一個參數(shù)走按照用戶名查詢,傳兩個參數(shù)按照姓和名查詢

直接看方法體有的同學(xué)可能不理解其中的巧妙,我來研究一下這個方法并記錄一下執(zhí)行規(guī)則
第一次調(diào)用: 通過 old 變量首先保存了之前成員的值,當(dāng)然這一次保存由于是第一次調(diào)用,所以他是一個undefined 然后給object[name]賦值了一個新的函數(shù),這個函數(shù)在運行的時候做了一個判斷,當(dāng)你傳遞的實參數(shù)量與你定義函數(shù)形參數(shù)量一致的時候就執(zhí)行該函數(shù)由此可得:

第二次調(diào)用:關(guān)鍵是否則,判斷一下old是否是函數(shù),如果是那調(diào)用old就會執(zhí)行上面第一次得出的邏輯,同理可得:

第三次調(diào)用:同理可得:

以上是一個注冊的順序,當(dāng)我們調(diào)用時傳遞0個參數(shù),他會從最后一個開始執(zhí)行,當(dāng)形參數(shù)量相等就會直接執(zhí)行當(dāng)前的方法,如果不相等就會執(zhí)行old也就是上一個find的邏輯,類似于冒泡執(zhí)行,等到執(zhí)行到第一次注冊的邏輯判斷時形參數(shù)量相等了,就直接執(zhí)行第一次注冊的方法,執(zhí)行打印 "查詢所有用戶"
searcher.find() // 查詢所有用戶
總結(jié)
其實就是用到了閉包,將閉包形成了閉包鏈把我們傳遞的方法依次注冊。在調(diào)用的時候從最后一個有序的去找,用這種非常巧妙的方式,用極少的代碼就實現(xiàn)了一個函數(shù)重載的效果,函數(shù)重載雖然說你不一定能用到,但是通過去解析這個addMethod,我們可以感受到有這么智慧的實現(xiàn)方案,肯定對你將來實現(xiàn)某一些東西的時候,有所啟發(fā)。
到此這篇關(guān)于詳解如何通過JavaScript實現(xiàn)函數(shù)重載的文章就介紹到這了,更多相關(guān)JavaScript函數(shù)重載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS?new操作原理及手寫函數(shù)模擬實現(xiàn)示例
這篇文章主要為大家介紹了JS?new操作原理及手寫函數(shù)模擬實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
uniapp中table表格設(shè)置寬度無效的原因以及解決方法
項目中遇到table表格單元格不整齊、錯位等情況,下面這篇文章主要給大家介紹了關(guān)于uniapp中table表格設(shè)置寬度無效的原因以及解決方法,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04
JS實現(xiàn)金額轉(zhuǎn)換(將輸入的阿拉伯?dāng)?shù)字)轉(zhuǎn)換成中文的實現(xiàn)代碼
這篇文章介紹了JS實現(xiàn)金額轉(zhuǎn)換(將輸入的阿拉伯?dāng)?shù)字)轉(zhuǎn)換成中文的實現(xiàn)代碼,有需要的朋友可以參考一下,希望對大家有用2013-09-09
JavaScript中通過閉包解決只能取得包含函數(shù)中任何變量最后一個值的問題
JavaScript中解決閉包只能取得包含函數(shù)中任何變量最后一個值的問題2010-08-08
簡易版本JSON.stringify的實現(xiàn)及其六大特性詳解
最近做項目發(fā)現(xiàn)JSON.stringify()使用場景真的挺多,我們都知道JSON.stringify()的作用是將JavaScript對象轉(zhuǎn)換為JSON字符串,下面這篇文章主要給大家介紹了JSON.stringify的實現(xiàn)及其六大特性的相關(guān)資料,需要的朋友可以參考下2021-10-10
typescript基本數(shù)據(jù)類型HTMLElement與Element區(qū)別
這篇文章主要為大家介紹了typescript基本數(shù)據(jù)類型HTMLElement與Element區(qū)別詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
javascript使用正則獲取url上的某個參數(shù)
使用indexOf取得?之后的參數(shù),以&使split進(jìn)行分割成數(shù)組,下面展示了一個從url上獲取名為MenuCode參數(shù)的過程2014-09-09

