深入理解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方法,如果還不支持,就用dom0級的方法添加事件

  這個過程,在addEvent函數每次調用的時候都要走一遍,其實,如果瀏覽器支持其中的一種方法,那么它就會一直支持了,就沒有必要再進行其他分支的檢測了。也就是說,if語句不必每次都執行,代碼可以運行的更快一些

  解決方案就是惰性載入

 

函數重寫

  在介紹惰性函數之前,首先介紹函數重寫技術。由於一個函數可以返回另一個函數,因此可以用新的函數來覆蓋舊的函數

function a(){
    console.log('a');
    a = function(){
        console.log('b');
    }
}

  這樣一來,第一次調用該函數時會console.log('a')會被執行;全局變量a被重定義,並被賦予新的函數。當該函數再次被調用時, console.log('b')會被執行

 

惰性函數

  惰性函數的本質就是函數重寫。所謂惰性載入,指函數執行的分支只會發生一次,有兩種實現惰性載入的方式

  1、第一種是在函數被調用時,再處理函數。函數在第一次調用時,該函數會被覆蓋為另外一個按合適方式執行的函數,這樣任何對原函數的調用都不用再經過執行的分支了。代碼重寫如下

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語句了

  但是,這種方法有個缺點,如果函數名稱有所改變,修改起來比較麻煩

  2、第二種是聲明函數時就指定適當的函數。把嗅探瀏覽器的操作提前到代碼加載的時候,在代碼加載的時候就立刻進行一次判斷,以便讓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;
        }
    }
})();

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM