利用函式的惰性載入提高 javascript 程式碼效能

迷渡發表於2014-06-09

在 javascript 程式碼中,因為各瀏覽器之間的行為的差異,我們經常會在函式中包含了大量的 if 語句,以檢查瀏覽器特性,解決不同瀏覽器的相容問題。例如,我們最常見的為 dom 節點新增事件的函式:

function addEvent (type, element, fun) {
    if (element.addEventListener) {
        element.addEventListener(type, fun, false);
    }
    else if(element.attachEvent){
        element.attachEvent('on' + type, fun);
    }
    else{
        element['on' + type] = fun;
    }
}

每次呼叫 addEvent 函式的時候,它都要對瀏覽器所支援的能力進行檢查,首先檢查是否支援 addEventListener 方法,如果不支援,再檢查是否支援 attachEvent 方法,如果還不支援,就用 dom 0 級的方法新增事件。這個過程,在 addEvent 函式每次呼叫的時候都要走一遍,其實,如果瀏覽器支援其中的一種方法,那麼他就會一直支援了,就沒有必要再進行其他分支的檢測了,也就是說,if 語句不必每次都執行,程式碼可以執行的更快一些。

解決的方案就是稱之為惰性載入的技巧。

所謂惰性載入,就是說函式的 if 分支只會執行一次,之後呼叫函式時,直接進入所支援的分支程式碼。有兩種實現惰性載入的方式,第一種事函式在第一次呼叫時,對函式本身進行二次處理,該函式會被覆蓋為符合分支條件的函式,這樣對原函式的呼叫就不用再經過執行的分支了,我們可以用下面的方式使用惰性載入重寫 addEvent()

function addEvent (type, element, fun) {
    if (element.addEventListener) {
        addEvent = function (type, element, fun) {
            element.addEventListener(type, fun, false);
        }
    }
    else if(element.attachEvent){
        addEvent = function (type, element, fun) {
            element.attachEvent('on' + type, fun);
        }
    }
    else{
        addEvent = function (type, element, fun) {
            element['on' + type] = fun;
        }
    }
    return addEvent(type, element, fun);
}

在這個惰性載入的 addEvent() 中,if 語句的每個分支都會為 addEvent 變數賦值,有效覆蓋了原函式。最後一步便是呼叫了新賦函式。下一次呼叫 addEvent() 的時候,便會直接呼叫新賦值的函式,這樣就不用再執行 if 語句了。

第二種實現惰性載入的方式是在宣告函式時就指定適當的函式。這樣在第一次呼叫函式時就不會損失效能了,只在程式碼載入時會損失一點效能。一下就是按照這一思路重寫的 addEvent()

var addEvent = (function () {
    if (document.addEventListener) {
        return function (type, element, fun) {
            element.addEventListener(type, fun, false);
        }
    }
    else if (document.attachEvent) {
        return function (type, element, fun) {
            element.attachEvent('on' + type, fun);
        }
    }
    else {
        return function (type, element, fun) {
            element['on' + type] = fun;
        }
    }
})();

這個例子中使用的技巧是建立一個匿名的自執行函式,通過不同的分支以確定應該使用那個函式實現,實際的邏輯都一樣,不一樣的地方就是使用了函式表示式(使用了 var 定義函式)和新增了一個匿名函式,另外每個分支都返回一個正確的函式,並立即將其賦值給變數 addEvent

惰性載入函式的優點只執行一次 if 分支,避免了函式每次執行時候都要執行 if 分支和不必要的程式碼,因此提升了程式碼效能,至於那種方式更合適,就要看您的需求而定了。

相關閱讀

相關文章