摘要:但是我們知道中是沒有重載的為什么沒重載不是的特性也會(huì)有的嗎,因?yàn)楹竺娑x的函數(shù)會(huì)覆蓋前面的同名函數(shù),但是重載那么好用,我們想在實(shí)現(xiàn)函數(shù)重載該怎么辦呢今天就來給大家講講在里面實(shí)現(xiàn)函數(shù)重載的兩個(gè)思路。這就是閉包的核心作用。
大家都知道,所謂重載,就是一組相同的函數(shù)名,有不同個(gè)數(shù)的參數(shù),在使用時(shí)調(diào)用一個(gè)函數(shù)名,傳入不同參數(shù),根據(jù)你的參數(shù)個(gè)數(shù),來決定使用不同的函數(shù)!重載這個(gè)在JAVA這些經(jīng)典的編程語言里面都很好用,可以說調(diào)用同一個(gè)方法名用不同的參數(shù)就可以為所欲為了。
但是我們知道JavaScript中是沒有重載的(為什么沒重載?不是JAVA的特性JavaScript也會(huì)有的嗎?),因?yàn)楹竺娑x的函數(shù)會(huì)覆蓋前面的同名函數(shù),但是重載那么好用,我們想在JavaScript實(shí)現(xiàn)函數(shù)重載該怎么辦呢?
今天就來給大家講講在JavaScript里面實(shí)現(xiàn)函數(shù)重載的兩個(gè)思路。(零基礎(chǔ)的同學(xué)打擾了,這篇不太適合你,需要點(diǎn)面向?qū)ο蠡A(chǔ)。)
第一種方法:這種方法比較簡(jiǎn)單,給一個(gè)思路,大家肯定都能理解,就是函數(shù)內(nèi)部用switch語句,根據(jù)傳入?yún)?shù)的個(gè)數(shù)調(diào)用不同的case語句,從而功能上達(dá)到重載的效果。
這種方法簡(jiǎn)單粗暴。但是對(duì)于一個(gè)正在學(xué)習(xí)js的人來說,這種方法未免太敷衍了。(那么沒技術(shù)含量,怎么能讓我變成前端開發(fā)大神呢?)
下面重點(diǎn)介紹一下第二種,老實(shí)說我第一次看的時(shí)候很吃力,看了一個(gè)小時(shí)才捋清楚,因?yàn)橛械闹R(shí)點(diǎn)雖然看過了但是不熟悉。(干貨很足,別看走神)
第二種方法:我們這個(gè)例子,是如果你不傳入?yún)?shù),就會(huì)輸出所有的人,輸入firstname,就會(huì)輸出匹配的人,如果輸入全名的人,也會(huì)輸出匹配的人。如果用重載的話,用戶體驗(yàn)確實(shí)會(huì)很好(這個(gè)例子是我以前學(xué)習(xí)時(shí)從網(wǎng)上扒下來的,很經(jīng)典,具有代表性,但是他們都沒有寫實(shí)現(xiàn)過程,所以今天我來給大家說講一下)
//第二種實(shí)現(xiàn)重載的方法 function method(obj,name,fnc){ var old = obj[name]; console.log(old instanceof Function); obj[name] = function(){ console.log(arguments.length+" "+fnc.length); if(arguments.length === fnc.length){//判斷參數(shù)是否對(duì)應(yīng) return fnc.apply(this,arguments);//指向?qū)?yīng)的函數(shù) }else if(typeof old === "function"){ return old.apply(this,arguments); } } } //定義一個(gè)用來查找和輸出的數(shù)組 var people = { values:["Zhang san","Li si","Wang wu"] }; //重載無參數(shù)查找方法,會(huì)輸出所有人 method(people,"find",function(){ console.log("無參數(shù)"); return this.values; }) //重載1個(gè)參數(shù)查找方法,輸入firstname參數(shù),找打匹配firstname的人 method(people,"find",function(firstname){ console.log("一個(gè)參數(shù)"); 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; }) //重載2個(gè)參數(shù)查找方法,輸入全名,找到對(duì)應(yīng)的人 method(people,"find",function(firstname,lastname){ console.log("兩個(gè)參數(shù)"); var ret = []; for(var i = 0;i < this.values.length;i++){ if(this.values[i] == firstname + " " + lastname){ ret.push(this.values[i]) } } return ret; }) //調(diào)用 console.log(people.find()); console.log(people.find("Zhang"));
思路:這段代碼第一眼看的時(shí)候肯定是懵的,再看一次好像有點(diǎn)思路,再看就又懵了。
其實(shí)呢,這種方法巧妙的運(yùn)用了JavaScript的閉包原理(重點(diǎn)),既然js后面的函數(shù)會(huì)覆蓋前面的同名函數(shù),我就強(qiáng)行讓所有的函數(shù)都留在內(nèi)存里,等我需要的時(shí)候再去找它。
有了這個(gè)想法,是不是就想到了閉包,函數(shù)外訪問函數(shù)內(nèi)的變量,從而使函數(shù)留在內(nèi)存中不被刪除。這就是閉包的核心作用。
實(shí)現(xiàn)過程:
我們看一下上面這段代碼,最重要的是method方法的定義:這個(gè)方法中最重要的一點(diǎn)就是這個(gè)old,這個(gè)old真的很巧妙。它的作用相當(dāng)于一個(gè)指針,指向上一次被調(diào)用的method函數(shù),這樣說可能有點(diǎn)不太懂,我們根據(jù)代碼來說,js的解析順序從上到下為。
1.解析method(先不管里面的東西)
2.method(people,"find",function() ) 執(zhí)行這句的時(shí)候,它就回去執(zhí)行上面定義的方法,然后此時(shí)old的值為空,因?yàn)槟氵€沒有定義過這個(gè)函數(shù),所以它此時(shí)是undefined。
然后繼續(xù)執(zhí)行,這時(shí)候我們才定義 obj[name] = function()。
然后js解析的時(shí)候發(fā)現(xiàn)返回了fnc函數(shù),更重要的是fnc函數(shù)里面還調(diào)用了method里面的變量,這不就是閉包了!
因?yàn)閒nc函數(shù)的實(shí)現(xiàn)是在調(diào)用時(shí)候才會(huì)去實(shí)現(xiàn),所以js就想,這我執(zhí)行完也不能刪除啊,要不外面那個(gè)用啥,就留著吧先(此處用apply函數(shù)改變了fnc函數(shù)內(nèi)部的this指向)
3.好了第一次method的使用結(jié)束了,開始了第二句,method(people,"find",function(firstname) 然后這次使用的時(shí)候,又要執(zhí)行old = obj[name]。
此時(shí)的old是什么,是函數(shù)了,因?yàn)樯弦粭l語句定義過了,而且沒有刪除,那我這次的old實(shí)際上指向的是上次定義的方法,它起的作用好像一個(gè)指針,指向了上一次定義的 obj[name]。
然后繼續(xù)往下解析,又是閉包,還得留著。
4.第三句的method調(diào)用開始了,同理old指向的是上次定義的 obj[name] 同樣也還是閉包,還得留著。
5.到這里,內(nèi)存中實(shí)際上有三個(gè) obj[name],因?yàn)槿蝝ethod的內(nèi)存都沒有刪除,這是不是實(shí)現(xiàn)了三個(gè)函數(shù)共存,同時(shí)還可以用old將它們聯(lián)系起來是不是很巧妙
6.我們 people.find() 的時(shí)候,就會(huì)最先調(diào)用最后一次調(diào)用method時(shí)定義的function,如果參數(shù)個(gè)數(shù)相同 也就是 arguments.length === fnc.length 那么就執(zhí)行就好了,也不用找別的函數(shù)了,如果不相同的話,那就得用到old了 return old.apply(this,arguments);
old指向的是上次method調(diào)用時(shí)定義的函數(shù),所以我們就去上一次的找,如果找到了,繼續(xù)執(zhí)行 arguments.length === fnc.length 如果找不到,再次調(diào)用old 繼續(xù)向上找,只要你定義過,肯定能找到的。
總結(jié):運(yùn)用閉包的原理使三個(gè)函數(shù)共存于內(nèi)存中,old相當(dāng)于一個(gè)指針,指向上一次定義的function,每次調(diào)用的時(shí)候,決定是否需要尋找。
最后來看看執(zhí)行輸出結(jié)果:
執(zhí)行過程很容易說明這一點(diǎn):首先第一次調(diào)用的時(shí)候 old肯定不是函數(shù),所以instance判斷是false,繼續(xù)調(diào)用的話就會(huì)為true。
然后,我們調(diào)用method的順序,是從沒有參數(shù)到兩個(gè)參數(shù),所以我們最先調(diào)用find方法,是最后一次method調(diào)用時(shí)定義的,所以fnc的length長(zhǎng)度是2.然后向上找,length為1,最后終于找到了length為0的然后執(zhí)行,輸出。
好了,今天的內(nèi)容就那么多吧!要是你也喜歡,就轉(zhuǎn)發(fā)給更多朋友學(xué)習(xí)吧!
喜歡的朋友也可以關(guān)注我的公眾號(hào):網(wǎng)頁前端開發(fā)學(xué)習(xí),發(fā)現(xiàn)更多好文哦!
推薦好文:作為一名前端開發(fā)工程師,你必須掌握的WEB模板引擎:Handlebars
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/96076.html
摘要:事實(shí)上語言當(dāng)中有的內(nèi)容,比如函數(shù)循環(huán)結(jié)構(gòu)體宏等等內(nèi)容,也都有,所以大家千萬不要認(rèn)為語言白學(xué)了哈因?yàn)橹耙呀?jīng)完整更新過語言的博客有需要可以往前翻,所以這里直接介紹相對(duì)語言當(dāng)中新增的內(nèi)容,而本章引入的內(nèi)容是的關(guān)鍵字命名空間缺省參數(shù)函數(shù)重載。 ...
摘要:繼承方式繼承方式限定了基類成員在派生類中的訪問權(quán)限,包括公有的私有的和受保護(hù)的。所以子類給父類引用賦值也是可以的,相當(dāng)于給子類對(duì)象中繼承的父類部分起了別名。如圖成員函數(shù)也是如此,當(dāng)子類與父類具有函數(shù)名相同的函數(shù)時(shí),還是符合就近原則。 ...
摘要:函數(shù)重載這個(gè)概念是在一些強(qiáng)類型語言中才有的,依托于,這也算是一門強(qiáng)類型語言了,所以就會(huì)有需要用到這種聲明的地方。 使用TypeScript已經(jīng)有了一段時(shí)間,這的確是一個(gè)好東西,雖說在使用的過程中也發(fā)現(xiàn)了一些bug,不過都是些小問題,所以整體體驗(yàn)還是很不錯(cuò)的。 TypeScript之所以叫Type,和它的強(qiáng)類型是分不開的,這也是區(qū)別于JavaScript最關(guān)鍵的一點(diǎn),類型的聲明可以直...
摘要:檢查當(dāng)前上下文中的參數(shù),建立該對(duì)象下的屬性與屬性值。檢查當(dāng)前上下文的函數(shù)聲明,也就是使用關(guān)鍵字聲明的函數(shù)。如果該變量名的屬性已經(jīng)存在,為了防止同名的函數(shù)被修改為,則會(huì)直接跳過,原屬性值不會(huì)被修改。 上一篇:《javascript高級(jí)程序設(shè)計(jì)》筆記:內(nèi)存與執(zhí)行環(huán)境showImg(https://segmentfault.com/img/bVY4xr?w=1146&h=374); 上篇文章...
摘要:下面來看看常用的本地存儲(chǔ)。缺點(diǎn)不支持,低版本不支持,并且不支持查詢語言,簡(jiǎn)稱為,是在瀏覽器中保存結(jié)構(gòu)化數(shù)據(jù)的一種數(shù)據(jù)庫。它類似數(shù)據(jù)庫的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)機(jī)制,代替了廢棄已久的,它能夠在客戶端存儲(chǔ)大量的結(jié)構(gòu)化數(shù)據(jù),并且使用索引高效檢索的。 一、引言 隨著瀏覽器的處理能力不斷增強(qiáng),越來越多的網(wǎng)站開始考慮將數(shù)據(jù)存儲(chǔ)在「客戶端」,那就不得不談?wù)劚镜卮鎯?chǔ)了。本地存儲(chǔ)的好處顯而易見,一是避免取回?cái)?shù)據(jù)前...
閱讀 1412·2021-11-24 09:39
閱讀 3693·2021-11-24 09:39
閱讀 1868·2021-11-16 11:54
閱讀 1469·2021-09-30 09:47
閱讀 1717·2021-09-26 10:16
閱讀 2351·2021-09-22 15:33
閱讀 1463·2021-09-14 18:01
閱讀 2447·2021-09-07 09:59