您好,登錄后才能下訂單哦!
小編這次要給大家分享的是如何實(shí)現(xiàn)JavaScript函數(shù)重載,文章內(nèi)容豐富,感興趣的小伙伴可以來了解一下,希望大家閱讀完這篇文章之后能夠有所收獲。
上個(gè)星期四下午,接到了網(wǎng)易的視頻面試(前端實(shí)習(xí)生第二輪技術(shù)面試)。面了一個(gè)多小時(shí),自我感覺面試得很糟糕的,因?yàn)閱柕降暮芏鄦栴}都很難,根本回答不上來。不過那天晚上,還是很驚喜的接到了HR面電話?,F(xiàn)在HR面試的結(jié)果還沒有出來,聽說要等到下周二才出,所以再好好等幾天哈。
前面說了這多的廢話,現(xiàn)在是時(shí)候和伙伴們分享一下面試干貨哈。因?yàn)槎鎲柕降膬?nèi)容還挺多的,所以這里就不全部列舉出來了。這里只討論一下函數(shù)的重載。
下面是面試時(shí)的對話,“面”指面試官,“我”就是我~
面:你能說說JS怎么實(shí)現(xiàn)函數(shù)的重載嗎?
我:因?yàn)镴S的參數(shù)是可變長度的,是沒有重載的!也是沒必要用重載的!
面:怎么沒必要使用重載?你先告訴什么是重載?
我: 重載就是一組具有相同名字、不同參數(shù)列表的函數(shù)(方法)。
面:對的,那為什么你還說JS沒有重載,也沒必要使用重載呢?
我當(dāng)時(shí)一臉懵逼了,因?yàn)椴恢烂嬖嚬俚降资窍胍嘉沂裁矗?span>因?yàn)槲矣浀谩禞S高級程序設(shè)計(jì)》里是提到過函數(shù)是沒有重載的?。ê髞聿榱艘幌?,在第三版的66頁,親們可以自己翻開書本看看),但是現(xiàn)在面試官不同意我的回答啊,就是說在他看來,JS是有重載的,我不能堅(jiān)持說沒有重載啊。所以我就往重載的概念方向靜靜的思考了片刻,然后想到了使用arguments對象進(jìn)行判斷。于是:
我:我覺得,如果JS函數(shù)需要實(shí)現(xiàn)重載的話,可以根據(jù)arguments對象的length值進(jìn)行判斷。
面: 你可以寫個(gè)例子出來給我看嗎?
然后,我就在輸入框里面寫了如下的代碼:
function overLoading() { // 根據(jù)arguments.length,對不同的值進(jìn)行不同的操作 switch(arguments.length) { case 0: /*操作1的代碼寫在這里*/ break; case 1: /*操作2的代碼寫在這里*/ break; case 2: /*操作3的代碼寫在這里*/ //后面還有很多的case...... } }
我把代碼發(fā)給了面試官。
面:對,這就是重載的一種實(shí)現(xiàn)的方法!不過你能不能想出一個(gè)更好的方法呢?
我: 暫時(shí)就想到這一種方法了。
好吧,跟面試官的對話就寫這么多了。他說問我能不能想出一個(gè)更好的辦法,意味著肯定還有其他我不知道的方法。所以,后來就開始翻書本查找。哈哈,終于在JQuery之父John Resig寫的《secrets of the JavaScript ninja》找到了一個(gè)絕佳巧妙的方法!那種方法充分的利用了閉包的特性!
在介紹這個(gè)方法之前,我們先來看看外國人名字組成哈,比如,John Resig,John是first-name,Resig是last-name,就相當(dāng)于我們的姓名由姓和名組成一樣。
我們現(xiàn)在有這樣的一個(gè)需求,有一個(gè)people對象,里面存著一些人名,如下:
var people = { values: ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"] };
我們希望people對象擁有一個(gè)find方法,當(dāng)不傳任何參數(shù)時(shí),就會把people.values里面的所有元素返回來;當(dāng)傳一個(gè)參數(shù)時(shí),就把first-name跟這個(gè)參數(shù)匹配的元素返回來;當(dāng)傳兩個(gè)參數(shù)時(shí),則把first-name和last-name都匹配的才返回來。因?yàn)閒ind方法是根據(jù)參數(shù)的個(gè)數(shù)不同而執(zhí)行不同的操作的,所以,我們希望有一個(gè)addMethod方法,能夠如下的為people添加find的重載:
addMethod(people, "find", function() {}); /*不傳參*/ addMethod(people, "find", function(a) {}); /*傳一個(gè)*/ addMethod(people, "find", function(a, b) {}); /*傳兩個(gè)*/
這時(shí)候問題來了,這個(gè)全局的addMethod方法該怎么實(shí)現(xiàn)呢?John Resig的實(shí)現(xiàn)方法如下,代碼不長,但是非常的巧妙:
function addMethod(object, name, fn) { var old = object[name]; //把前一次添加的方法存在一個(gè)臨時(shí)變量old里面 object[name] = function() { // 重寫了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); } } }
現(xiàn)在,我們一起來分析一個(gè)這個(gè)addMethod函數(shù),它接收3個(gè)參數(shù),第一個(gè)為要綁定方法的對象,第二個(gè)為綁定的方法名稱,第三個(gè)為需要綁定的方法(一個(gè)匿名函數(shù))。函數(shù)體的的分析已經(jīng)在注釋里面了。
OK,現(xiàn)在這個(gè)addMethod方法已經(jīng)實(shí)現(xiàn)了,我們接下來就實(shí)現(xiàn)people.find的重載啦!全部代碼如下:
//addMethod function addMethod(object, name, fn) { var old = object[name]; object[name] = function() { if(fn.length === arguments.length) { return fn.apply(this, arguments); } else if(typeof old === "function") { return old.apply(this, arguments); } } } var people = { values: ["Dean Edwards", "Alex Russell", "Dean Tom"] }; /* 下面開始通過addMethod來實(shí)現(xiàn)對people.find方法的重載 */ // 不傳參數(shù)時(shí),返回peopld.values里面的所有元素 addMethod(people, "find", function() { return this.values; }); // 傳一個(gè)參數(shù)時(shí),按first-name的匹配進(jìn)行返回 addMethod(people, "find", function(firstName) { var ret = []; for(var i = 0; i < this.values.length; i++) { if(this.values[i].indexOf(firstName) === 0) { ret.push(this.values[i]); } } return ret; }); // 傳兩個(gè)參數(shù)時(shí),返回first-name和last-name都匹配的元素 addMethod(people, "find", function(firstName, lastName) { var ret = []; for(var i = 0; i < this.values.length; i++) { if(this.values[i] === (firstName + " " + lastName)) { ret.push(this.values[i]); } } return ret; }); // 測試: console.log(people.find()); //["Dean Edwards", "Alex Russell", "Dean Tom"] console.log(people.find("Dean")); //["Dean Edwards", "Dean Tom"] console.log(people.find("Dean Edwards")); //["Dean Edwards"]
看完這篇關(guān)于如何實(shí)現(xiàn)JavaScript函數(shù)重載的文章,如果覺得文章內(nèi)容寫得不錯(cuò)的話,可以把它分享出去給更多人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。