網(wǎng)易面試官:請(qǐng)你實(shí)現(xiàn)一下JS重載?可不是TS重載哦!
什么是重載
我第一次看到重載這個(gè)詞還是在以前學(xué)習(xí)Java的時(shí)候,我一直覺(jué)得JavaScript是沒(méi)有重載的,直到TypeScript的出現(xiàn),所以我一直覺(jué)得JavaScript沒(méi)有重載,TypeScript才有,但是現(xiàn)在看來(lái)我是錯(cuò)的。
我理解的重載是:同樣的函數(shù),不同樣的參數(shù)個(gè)數(shù),執(zhí)行不同的代碼,比如:
/*
* 重載
*/
function fn(name) {
console.log(`我是${name}`)
}
function fn(name, age) {
console.log(`我是${name},今年${age}歲`)
}
function fn(name, age, sport) {
console.log(`我是${name},今年${age}歲,喜歡運(yùn)動(dòng)是${sport}`)
}
/*
* 理想結(jié)果
*/
fn('林三心') // 我是林三心
fn('林三心', 18) // 我是林三心,今年18歲
fn('林三心', 18, '打籃球') // 我是林三心,今年18歲,喜歡運(yùn)動(dòng)是打籃球
但是直接在JavaScript中這么寫(xiě),肯定是不行的,咱們來(lái)看看上面代碼的實(shí)際執(zhí)行結(jié)果,可以看到,最后一個(gè)fn的定義,把前面兩個(gè)都給覆蓋了,所以沒(méi)有實(shí)現(xiàn)重載的效果。
我是林三心,今年undefined歲,喜歡運(yùn)動(dòng)是undefined
我是林三心,今年18歲,喜歡運(yùn)動(dòng)是undefined
我是林三心,今年18歲,喜歡運(yùn)動(dòng)是打籃球
我的做法
其實(shí),想要實(shí)現(xiàn)理想的重載效果,我還是有辦法的,我可以只寫(xiě)一個(gè)fn函數(shù),并在這個(gè)函數(shù)中判斷arguments類數(shù)組的長(zhǎng)度,執(zhí)行不同的代碼,就可以完成重載的效果。
function fn() {
switch (arguments.length) {
case 1:
var [name] = arguments
console.log(`我是${name}`)
break;
case 2:
var [name, age] = arguments
console.log(`我是${name},今年${age}歲`)
break;
case 3:
var [name, age, sport] = arguments
console.log(`我是${name},今年${age}歲,喜歡運(yùn)動(dòng)是${sport}`)
break;
}
}
/*
* 實(shí)現(xiàn)效果
*/
fn('林三心') // 我是林三心
fn('林三心', 18) // 我是林三心,今年18歲
fn('林三心', 18, '打籃球') // 我是林三心,今年18歲,喜歡運(yùn)動(dòng)是打籃球
但是那位同學(xué)說(shuō),網(wǎng)易的面試官好像覺(jué)得這么實(shí)現(xiàn)可以是可以,但是還有沒(méi)有更好的實(shí)現(xiàn)方法,我就懵逼了。
高端做法
經(jīng)過(guò)了我的一通網(wǎng)上查找資料,發(fā)現(xiàn)了一種比較高端的做法,可以利用閉包來(lái)實(shí)現(xiàn)重載的效果。這個(gè)方法在JQuery之父John Resig寫(xiě)的《secrets of the JavaScript ninja》中,這種方法充分的利用了閉包的特性!
function addMethod(object, name, fn) {
var old = object[name]; //把前一次添加的方法存在一個(gè)臨時(shí)變量old里面
object[name] = function () { // 重寫(xiě)了object[name]的方法
// 如果調(diào)用object[name]方法時(shí),傳入的參數(shù)個(gè)數(shù)跟預(yù)期的一致,則直接調(diào)用
if (fn.length === arguments.length) {
return fn.apply(this, arguments);
// 否則,判斷old是否是函數(shù),如果是,就調(diào)用old
} else if (typeof old === "function") {
return old.apply(this, arguments);
}
}
}
addMethod(window, 'fn', (name) => console.log(`我是${name}`))
addMethod(window, 'fn', (name, age) => console.log(`我是${name},今年${age}歲`))
addMethod(window, 'fn', (name, age, sport) => console.log(`我是${name},今年${age}歲,喜歡運(yùn)動(dòng)是${sport}`))
/*
* 實(shí)現(xiàn)效果
*/
window.fn('林三心') // 我是林三心
window.fn('林三心', 18) // 我是林三心,今年18歲
window.fn('林三心', 18, '打籃球') // 我是林三心,今年18歲,喜歡運(yùn)動(dòng)是打籃球
參考資料
- 淺談JavaScript函數(shù)重載