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