JS惰性载入函数
惰性载入就是当第 1 次根据条件执行函数后,第 2 次调用函数时,就不再检测条件,直接执行函数。
【问题由来】
由于浏览器之间的行为差异,很多脚本会包含大量的条件检测,通过条件决定不同行为的浏览器执行不同的代码。
【设计思路】
- 当函数第 1 次被调用的时候,执行一次检测条件。
- 在第 1 次调用的过程中,使用另外一个根据条件检测,按合适方式执行的函数,覆盖掉第 1 次调用的函数。
- 当再次调用该函数时,不再是原来的函数,而是直接调用被覆盖后的函数,这样就不用再次执行条件检测了。
示例
在注册事件处理函数时,经常需要考虑浏览器的事件模型。先要检测当前浏览器是 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 实例对象时,就不再去检测浏览器的兼容性问题。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/23152.html