JavaScript 設計模式系列 – 自定義函式(惰性函式)

乘風gg發表於2019-02-28

本系列教程不會講得特別深,通過案例,就帶個入門,面試的時候,被問到能答出個所以來,在實際運用中,能把複雜的問題簡單化就夠了。

概念

其實在javascript裡函式可以動態定義的,如果建立了一個新函式並且將其分配給儲存了另外函式的同一個變數,那麼新函式覆蓋舊函式。

    var Obj = function () {
        alert(`乘風gg!`);
        Obj = function () {
            alert(`Double 乘風gg!`)
        };
    }
    Obj();//`乘風gg!`
    Obj();//`Double 乘風gg!`複製程式碼

這種自定義函式的作用在於,初始化,對,你沒看錯,就是初始化,一般用於初始化程式並且只僅需執行一次的時候,這種方式就非常有用了,這樣可以避免頻繁的邏輯判斷和避免重複的工作,提升應用程式的效能。

這種自定義函式其實也叫惰性函式的思想重寫原來的函式是有缺陷的。一不小心就踩坑

  • 當它重定義自身時已經新增到原始函式的任何屬性丟會丟失。

JavaScript 設計模式系列 – 自定義函式(惰性函式)

(上圖應該是首次定義)

  • 如果該函式使用了不同的名稱,比如分配給不同的變數或者以物件的方法來使用,那麼重定義部分將永遠不會發生,並且將會執行原始函式體。

JavaScript 設計模式系列 – 自定義函式(惰性函式)

練習

結合我畫的醜圖,下面我們來踩踩這兩個坑。
繼續上面的程式碼。

 Obj.property = `property`;
    //賦值給另一個不同名稱的變數
    var modify = Obj;
    //作為一個方法使用
    var _obj = {
        fn: Obj
    }
    //呼叫賦值給modify的情況
    modify();//`乘風gg!`
    modify();//`乘風gg!`
    console.log(modify.property);//`property`
    //作為一個方法來呼叫
    _obj.fn()//`乘風gg!`
    _obj.fn()//`乘風gg!`
    console.log(_obj.fn.property);//`property`
    //直接呼叫
    Obj();//`Double 乘風gg!`
    Obj();//`Double 乘風gg!`
    console.log(Obj.property);//`undefined`複製程式碼

正如我們預期一樣,每次呼叫modify,都是輸出`乘風gg`,並且還生產了一個新的函式,地址是777777,並且被Obj引用了,所以,函式modify是保持著第一次定義的舊函式,Obj是新函式,所以最後輸出`undefined`。

作用:

以前我們使用ajax處理瀏覽器相容的時候,不知道你們是不是這樣子寫的

 function createXHR() {
        var xhr = null;
        if (window.XMLHttpRequest) {
            xhr = new XMLHttpRequest;
        } else {
            try {
                xhr = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
                try {
                    xhr = new ActiveXObject("Msxml2.XMLHTTP");
                } catch (e) {
                    try {
                        xhr = new ActiveXObject("Msxml3.XMLHTTP");
                    } catch (e) {

                    }
                }
            }
        }
        return xhr;
    }
    var xhr = createXHR();
    var xhr2 = createXHR();複製程式碼

由於頁面肯定不止一次向伺服器傳送 ajax請求,那麼瀏覽器多次執行這段createXHR的函式的時候,頻繁的執行這段程式碼去判斷瀏覽器的相容性, 浪費了效能,其實只有第一次使用ajax的時候判斷瀏覽器的相容,然後重新定義這個ajax函式,不就好了嘛?我們來實現一下

function createXHR() {
    var xhr = null,
        flag = false,
        ary = [
            function () {
                return new XMLHttpRequest;
            },
            function () {
                return new ActiveXObject("Microsoft.XMLHTTP");
            },
            function () {
                return new ActiveXObject("Msxml2.XMLHTTP");
            },
            function () {
                return new ActiveXObject("Msxml3.XMLHTTP");
            }
        ];
    //迴圈遍歷這個陣列,看看陣列內的哪一個元素相容瀏覽器,如果相容,就賦值給給xhr,並且返回出去
    for (var i = 0, len = ary.length; i < len; i++) {
        var curFn = ary[i];
        try {
            xhr = curFn();
            createXHR = curFn;//重新定義createXHR ,第二次呼叫ajax請求,則直接使用這個方法
            flag = true;
            break;
        } catch (e) {
            //說明瀏覽器不相容,繼續迴圈
        }
    }
    if (!flag) {
         throw new Error("你的瀏覽器不支援 ,請升級瀏覽器");
    }
    return xhr;
}複製程式碼

其實還有一些方法也能達到惰性函式的思想,是利用單例模式(下一章會講到).

總結

  • 惰性函式的實現原理就是重新定義函式。
  • 惰性思想的精髓:能一次搞定的事,我絕不做第二次

最後歡迎大家指正,批評,督促。
github原始碼地址:github.com/Faithree/js…
參照案例書籍javascript模式

點贊是對我的最大支援和鼓勵

相關文章