所謂重載,就是一組相同的函數名,有不一樣個數的參數,在使用時調用一個函數名,傳入不一樣參數,根據你的參數個數,來決定使用不一樣的函數!可是咱們知道js中是沒有重載的,由於後定義的函數會覆蓋前面的同名函數,可是咱們又想實現函數重載該怎麼辦呢?閉包
這種方法比較簡單,給一個思路,你們確定都能理解,就是函數內部用switch語句,根據傳入參數的個數調用不一樣的case語句,從而功能上達到重載的效果。app
這種方法簡單粗暴函數
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"] }; method(people,"find",function(){ console.log("無參數"); return this.values; }) 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; }) 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"));
實現過程:咱們看一下上面這段代碼,最重要的是method方法的定義:這個方法中最重要的一點就是這個old,這個old真的很巧妙。它的做用至關於一個指針,指向上一次被調用的method函數,這樣說可能有點不太懂,咱們根據代碼來講,js的解析順序從上到下爲。this
1.解析method(先無論裏面的東西)prototype
2.method(people,"find",function() 執行這句的時候,它就回去執行上面定義的方法,而後此時old的值爲空,由於你尚未定義過這個函數,因此它此時是undefined,而後繼續執行,這是咱們才定義 obj[name] = function(),而後js解析的時候發現返回了fnc函數,更重要的是fnc函數裏面還調用了method裏面的變量,這不就是閉包了,由於fnc函數的實現是在調用時候纔會去實現,因此js就想,這我執行完也不能刪除啊,要不外面那個用啥,就留着吧先(此處用call函數改變了fnc函數內部的this指向)指針
3.好了第一次method的使用結束了,開始了第二句,method(people,"find",function(firstname) 而後此次使用的時候,又要執行old = obj[name]此時的old是什麼,是函數了,由於上一條語句定義過了,並且沒有刪除,那我此次的old實際上指向的是上次定義的方法,它起的做用好像一個指針,指向了上一次定義的 obj[name]。而後繼續往下解析,又是閉包,還得留着。code
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,每次調用的時候,決定是否須要尋找。
後續:說完上面的再對比下面的理解,會更深刻的理解原型與原型鏈
var array=[] addMethod(array,'sub0',function(){ return 0; }) addMethod(array,'sub0',function(prefix){ console.log("prefix===>",prefix); return prefix[0]; }) array.sub0([1,2,3,5]) //這裏是array對象擁有了sub0這樣的方法,而不是Array,addMethod是繼承 // 區別於方法直接做用於原型上 //例子 String的 startsWith 實現 function addstartsWithToString(){ if (typeof String.prototype.startsWith1 != 'function' ) { String.prototype.startsWith1 = function(subString){ return this.slice(0,subString.length)==subString } } } addstartsWithToString(); '120000'.startsWith1('1')