JavaScript 專題系列第十五篇,講解惰性函式
需求
我們現在需要寫一個 foo 函式,這個函式返回首次呼叫時的 Date 物件,注意是首次。
解決一:普通方法
var t;
function foo() {
if (t) return t;
t = new Date()
return t;
}複製程式碼
問題有兩個,一是汙染了全域性變數,二是每次呼叫 foo 的時候都需要進行一次判斷。
解決二:閉包
我們很容易想到用閉包避免汙染全域性變數。
var foo = (function() {
var t;
return function() {
if (t) return t;
t = new Date();
return t;
}
})();複製程式碼
然而還是沒有解決呼叫時都必須進行一次判斷的問題。
解決三:函式物件
函式也是一種物件,利用這個特性,我們也可以解決這個問題。
function foo() {
if (foo.t) return foo.t;
foo.t = new Date();
return foo.t;
}複製程式碼
依舊沒有解決呼叫時都必須進行一次判斷的問題。
解決四:惰性函式
不錯,惰性函式就是解決每次都要進行判斷的這個問題,解決原理很簡單,重寫函式。
var foo = function() {
var t = new Date();
foo = function() {
return t;
};
return foo();
};複製程式碼
更多應用
DOM 事件新增中,為了相容現代瀏覽器和 IE 瀏覽器,我們需要對瀏覽器環境進行一次判斷:
// 簡化寫法
function addEvent (type, el, fn) {
if (window.addEventListener) {
el.addEventListener(type, fn, false);
}
else if(window.attachEvent){
el.attachEvent('on' + type, fn);
}
}複製程式碼
問題在於我們每當使用一次 addEvent 時都會進行一次判斷。
利用惰性函式,我們可以這樣做:
function addEvent (type, el, fn) {
if (window.addEventListener) {
addEvent = function (type, el, fn) {
el.addEventListener(type, fn, false);
}
}
else if(window.attachEvent){
addEvent = function (type, el, fn) {
el.attachEvent('on' + type, fn);
}
}
}複製程式碼
當然我們也可以使用閉包的形式:
var addEvent = (function(){
if (window.addEventListener) {
return function (type, el, fn) {
el.addEventListener(type, fn, false);
}
}
else if(window.attachEvent){
return function (type, el, fn) {
el.attachEvent('on' + type, fn);
}
}
})();複製程式碼
當我們每次都需要進行條件判斷,其實只需要判斷一次,接下來的使用方式都不會發生改變的時候,想想是否可以考慮使用惰性函式。
重要參考
Lazy Function Definition Pattern
專題系列
JavaScript專題系列目錄地址:github.com/mqyqingfeng…。
JavaScript專題系列預計寫二十篇左右,主要研究日常開發中一些功能點的實現,比如防抖、節流、去重、型別判斷、拷貝、最值、扁平、柯里、遞迴、亂序、排序等,特點是研(chao)究(xi) underscore 和 jQuery 的實現方式。
如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果喜歡或者有所啟發,歡迎 star,對作者也是一種鼓勵。