• JS惰性载入函数与分支函数

    惰性载入函数和分支函数是 JS 高阶函数的两种具体应用场景,它们都是将函数作为返回值 return 到函数外部。

    JS惰性载入函数

    惰性载入就是当第 1 次根据条件执行函数后,第 2 次调用函数时,就不再检测条件,直接执行函数。

    【问题由来】

    由于浏览器之间的行为差异,很多脚本会包含大量的条件检测,通过条件决定不同行为的浏览器执行不同的代码。

    【设计思路】

    1. 当函数第 1 次被调用的时候,执行一次检测条件。
    2. 在第 1 次调用的过程中,使用另外一个根据条件检测,按合适方式执行的函数,覆盖掉第 1 次调用的函数。
    3. 当再次调用该函数时,不再是原来的函数,而是直接调用被覆盖后的函数,这样就不用再次执行条件检测了。

    示例

    在注册事件处理函数时,经常需要考虑浏览器的事件模型。先要检测当前浏览器是 DOM 模型,还是 IE 的事件模型,然后调用不同的方法进行注册。

    var addEvent = function (element, type, handle) {
        if (element.addEventListener) {
            element.addEventListener(type, handle, false);
        } else {
            element.attachEvent("on" + type, handle);
        }
    }
    addEvent(document, "mousemove", function () {
        console.log("移动鼠标:" + ((this.n) ? (++this.n) : (this.n = 1)));
    })
    addEvent(window, "resize", function () {
        console.log("改变窗口大小:"+ ((this.n) ? (++this.n) : (this.n = 1)));
    })

    如此简单的条件检测,如果在高频、巨量的操作中,每次调用 addEvent() 方法都需要做一次条件检测,无疑是不经济的。下面使用惰性载入方法,重写 addEvent() 函数。

    var addEvent = function (element, type, handle) {
        //先检测浏览器,然后把合适的操作函数覆盖掉当前addEvent()
        addEvent = element.addEventListener ? function (element, type, handle) {
            element.addEventListener(type, handle, false);
        } : function (element, type, handle) {
            element.attachEvent("on" + type, handle);
        };
        //在第一次执行addEvent函数时,修改了addEvent函数之后,必须执行一次
        addEvent(element, type, handle);
    }

    在上面代码中,当第 1 次调用 addEvent() 函数时做一次条件检测;然后根据浏览器选择相应的事件注册方法,同时把这个操作封装在一个匿名函数中;接着使用该函数覆盖掉 addEvent() 函数;最后执行第 1 次事件注册操作。这样,当第 2 次开始再次注册事件时,就不需要做条件检测了。

    JS分支函数

    分支函数与惰性载入函数都是解决条件检测的问题。分支函数类似面向对象编程的接口,对外提供相同的操作接口,内部实现则会根据不同的条件执行不同的操作。分支函数与惰性载入函数在设计原理上是非常相近的,只是在代码实现方面略有差异。

    示例

    使用分支函数解决浏览器兼容性的重复判断。解决浏览器兼容性的一般方法是使用 if 语句进行特性检测或能力检测,然后根据浏览器的不同,实现功能上的兼容。这样做的问题是,每执行一次代码,可能都需要进行一次浏览器兼容性方面的检测,这是没有必要的。

    分支函数的设计思路:在代码初始化执行的时候检测浏览器的兼容性,在之后的代码执行过程中,就不再进行检测。

    下面声明一个 XMLHttpRequest 实例对象。

    var XHR = function () {
        var standard = {
            createXHR : function () {
                return new XMLHttpRequest();
            }
        }
        var newActionXObject = {
            createXHR : function () {
                return new ActionXObject("Msxml2.XMLHTTP");
            } 
        }
        var oldActionXObject = {
            createXHR : function () {
                return new ActionXObject("Microsoft.XMLHTTP");
            }
        }
        if (standard.createXHR) {
            return standard;
        } else {
            try {
                newActionXObject.createXHR();
                return newActionXObject;
            } catch {
                oldActionXObject.createXHR();
                return oldActionXObject;
            }
        }
    } ();
    var xhr = XHR.createXHR();  //创建XMLHttpRequest实例对象

    在代码初始化执行之后,XHR 被初始化为一个对象,拥有 createXHR() 方法,该方法的实现已经在初始化阶段根据当前浏览器选择了合适的方法,当调用 XHR.createXHR() 方法创建 XMLHttpRequest 实例对象时,就不再去检测浏览器的兼容性问题。

更多...

加载中...