
js 函數的重載
我們知道,很多編程語言都有函數的重載。
所謂的重載,看定義:
重載,簡單說,就是函數或者方法有相同的名稱,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間,互相稱之為重載函數或者方法。
同名函數,根據傳入的參數類型不同,來執行對應的方法。
所以從這個定義中,我們能夠得出,js 并不具備函數的重載功能。
因為 js 不用對傳入的參數的類型,進行嚴格的定義。所以,即使我們寫了同名的函數,也只會導致后面的函數會將前面的函數覆蓋掉。
現在我們假設,即使 js 同名函數能夠共存,但是我們無法知道不同的同名函數分別接收什么類型的參數,同樣無法判斷該調用哪一個方法。
但是我們在平時寫代碼的過程中,有一種情況是比較常見的。
比如,我們現在有一個對象 People,有私有屬性 name 和 age。
因為 JavaScript 中沒有私有屬性,所以我們只能通過閉包來模擬私有屬性。
所以,我們在構造函數內部定義 name 和 age 對象,通過 get,set 接口來統一讀取和修改他們。
代碼見下面所示。
var
用的時候,我們可以這樣:
// 防止構造函數中沒用 new 我們檢測了一下 this 的指向
可以看到,這里,我們通過用了 get 和 set 函數,來對外提供接口。
那么,我們想一想,我們能不能將這兩個函數合并一下,通過同一個函數,來實現這兩種功能呢?
答案當然是肯定的,我么可以改寫一下我們之前的構造函數:
var
再看下我們的使用過程:
var
可以看出來,這樣一改,這個接口調用起來就很方便了。
雖然乍一看,這樣該寫了以后,好像不太好理解。但是如果習慣了這種寫法以后,你會感受到這種寫法的奇妙之處。簡直太方便了,傳一個參數就是拿值,傳兩個參數,就是改寫對應的值。
當然這種寫法,是我們在架構我們的項目的時候,有這種意識,這當然算是一種比較好的寫法了。
但是如果我們剛開始架構的時候,是這樣寫的:
var
隨著我們項目的進行,可能在原型鏈上,有很多方法都用到了 this._name 或者 this._age。
這個時候,如果想要遷移我們的變量成閉包內部的變量,當然是不劃算的,改寫起來太麻煩了。
但是如果我們又想要提供一個類似于之前的 o 函數,該怎么做呢?
也許又童鞋得第一反應是,這還不簡單,三下五除二的進行了如下的拓展:
People
這樣寫固然沒有問題,但是還是不太具備擴展性。
如果,某一天,我們突發奇想,想要拓展一下這個 o 方法,當不傳參數的時候,我們想要列出實例上所有的屬性。
我們固然可以通過重載這個 o 方法來實現,但是總感覺不夠優雅。
現在有一種更為優雅的方式。
我們可以創建一個 overload 方法用于重載:
function
我們可以這樣調用:
overload
我們還可以繼續擴展:
overload
可以看出來,我們的重載函數,非常的強大,擴展性也是非常的強。
可以對任意一個對象上的函數進行重載,當然這里是通過識別參數的個數來進行重載的,這也是現階段 js 中所能做到的極限了。
這個小小的 overload 方法,同樣也是通過閉包來實現的重載。
原理就是通過比較函數的參數與傳入的參數個數是否相等,相等則用調用當前函數進行執行。如果不相等,那么調用 old 函數,進行執行。而 old 函數同樣會遞歸執行參數個數判斷這一過程,這樣就實現了根據參數的個數對函數進行重載。