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

但是JS不支持函數(shù)重載,所以說(shuō)如果你寫(xiě)成已上的形式,無(wú)論你怎么調(diào)用,一定是調(diào)用最后一個(gè)函數(shù),因?yàn)樽詈笠粋€(gè)函數(shù)把前面的全部覆蓋了
不傳參數(shù)試一下,你看永遠(yuǎn)都是走最后一個(gè)函數(shù)的log
searcher.find() // 按照姓和名用戶查詢
那有什么辦法呢?在很早的時(shí)候jQuery之父John Resig 他就已經(jīng)提出了一個(gè)想法,我們能不能實(shí)現(xiàn)一個(gè)方法來(lái)幫助我們?cè)趈s中完成函數(shù)重載?
于是他想出了一個(gè)addMethod方法,就是當(dāng)我要重載的時(shí),我不直接去定義函數(shù),因?yàn)橹苯佣x函數(shù)就會(huì)出現(xiàn)一個(gè)永遠(yuǎn)只調(diào)用最后一個(gè)函數(shù)的問(wèn)題,而調(diào)用addMethod來(lái)定義函數(shù),把對(duì)象傳進(jìn)去,把函數(shù)的名字傳進(jìn)去,把函數(shù)的實(shí)現(xiàn)傳進(jìn)去,后面依次同理
addMethod(searcher, 'find', () => {
console.log('查詢所有用戶')
})
addMethod(searcher, 'find', (name) => {
console.log('按照用戶名稱查詢')
})
addMethod(searcher, 'find', (firstName, lastName) => {
console.log('按照姓和名用戶查詢')
})寫(xiě)成這種格式之后,后面調(diào)用searcher.find()就能夠完成函數(shù)重載,問(wèn)題是這個(gè)方法我們得要自己實(shí)現(xiàn),那么如何來(lái)實(shí)現(xiàn)? 這個(gè)方法他接受三個(gè)參數(shù),如果你不加處理的話你可能寫(xiě)成下面函數(shù)一樣,給對(duì)象加一個(gè)屬性,這個(gè)屬性等于一個(gè)函數(shù),調(diào)用這個(gè)函數(shù)實(shí)際上就是在運(yùn)行定義的實(shí)現(xiàn)函數(shù)fn,把this綁定帶過(guò)去 然后把傳遞過(guò)來(lái)的arguments帶過(guò)去
function addMethod(object, name, fn) {
object[name] = function () {
fn.apply(this, arguments)
}
}僅僅這么些還是搞不定,因?yàn)槊看握{(diào)用addMethod最后一次調(diào)用一定會(huì)把object里面同一個(gè)屬性給覆蓋掉,那么如何處理?看下方代碼
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ù)走查詢所有用戶,傳一個(gè)參數(shù)走按照用戶名查詢,傳兩個(gè)參數(shù)按照姓和名查詢

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

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

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

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

