首页 > 编程笔记 > JavaScript笔记 > JS函数

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 实例对象时,就不再去检测浏览器的兼容性问题。

所有教程

优秀文章