惰性模式:减少每次代码执行时的重复性的分支判断,通过对对象重定义来屏蔽原对象中的分支判断。
问题代码:
function on = function(dom, type, fn) {
if (dom.addEventListener) {
dom.addEventListener(type, fn, false);
} else if (dom.attachEvent) {
dom.attachEvent('on' + type, fn);
} else {
dom['on' + type] = fn;
}
}
每次为元素添加事件时,都会走一遍能力检测,这是多余的,因为在同一个浏览器中两次执行方法,能力检测是不可能走两个不同的分支的。
既然第一次执行时已经判断过了,而且以后再执行是不必要的,那么就可以在第一次执行后就重新定义它。这就是惰性模式的精髓。
工作中这种模式思想有两种实现方式,
- 第一种就是在文件加载进来时通过闭包执行该方法对其重新定义。
不过这样会使页面加载时占用一定的资源。
var on = function(dom, type, fn) {
if (document.addEventListener) {
return function(dom, type, fn) {
dom.addEventListener(type, fn, false);
}
} else if (document.attachEvent) {
return function(dom, type, fn) {
dom.attachEvent('on' + type, fn);
}
} else {
return function(dom, type, fn) {
dom['on' + type'] = fn;
}
}
}();
- 第二种方式是在第一种方式寄出上做一次延迟执行,在函数第一次调用的时候对其重定义。
这么做的好处就是减少文件加载时的资源消耗,但是却在第一次执行时有一定的资源消耗。
function on(dom, type, fn) {
if (dom.addEventListener) {
on = function(dom, type, fn) {
dom.addEventListener(type, fn, false);
}
} else if (dom.attachEvent) {
on = function(dom, type, fn) {
dom.attachEvent('on' + type, fn);
}
} else {
on = function(dom, type, fn) {
dom['on' + type] = fn;
}
}
// 执行重定义on方法
on(dom, type, fn);
}
第二种方式与第一种实现方式的不同之处在于,首先,内部对元素dom执行能力检测并显式重写,其次,原始函数在函数的最末尾重新执行一遍来绑定事件。不过在文件加载后on方法还没能重新被定义。所以我们还需等到某一元素绑定事件时(调用on方法时),on才能被重定义。
所以你可以看出这种方式实质上是对消耗的一种惰性推移,有时候是很有必要的,尤其在重定义时消耗资源比较大而且想尽量早地预览到页面时。
如今浏览器繁多,尤其在国内更是复杂,很多功能在不同浏览器中实现不以,所以很多代码为兼容各个浏览器写的分支特别臃肿,有了这种模式,就能使臃肿的代码执行效率得到提高了。比如创建XHR对象。
总结:
惰性模式是一种拖延模式,由于对象的创建或者数据的计算会花费高昂的代价(如页面刚加载时无法辨别是该浏览器支持某个功能,此时创建对象是不够安全的),因此页面之初会延迟对这一类对象的创建。惰性模式又分为两种:第一种是文件加载后立即执行对象方法来重定义对象。第二种是当第一次使用方法对象时重定义对象。
对于第一种方式,由于文件加载时执行,因此会占用一些资源。
对于第二种方式由于在第一次使用时重定义对象,以致第一次执行时间增加。
有时候两种方式对资源的开销都是可接受的,因此到底使用哪种方式,要看具体需求而定。
以上内容摘抄自《JavaScript设计模式》