浏览器检测的问题
由于各浏览器之间的行为差异,js代码中需要大量的 if 语句,检查浏览器特性,解决浏览器兼容问题。
比如为 dom 节点添加事件的函数:
function addEvent (type, element, fun) {
if (element.addEventListener) {
element.addEventListener(type, fun, false);
}
else if(element.attachEvent){
element.attachEvent('on' + type, fun);
}
else{
element['on' + type] = fun;
}
}
上面的代码中,每次调用 addEvent 函数都要对浏览器所支持的能力进行检查,
首先检查是否支持 addEventListener 方法,如果不支持,再检查是否支持 attachEvent 方法,如果还不支持,就用 dom 0 级的方法添加事件。
并且上面的检测过程,在 addEvent 函数每次调用的时候都要重复执行一遍。
然而事实上,如果浏览器支持其中的一种方法,那么它就会一直支持了,自然也就没有必要再执行其他分支检测了。
懒加载
由上面的分析可知,我们需要一种方法,不必每次都执行if 语句,只在第一次需要进行浏览器检测的地方执行检测,达到代码运行的更快一些的效果,这样的方法称为“懒加载”方法。
所谓懒加载,即指函数的if分支只会执行一次,之后调用函数时,直接进入所支持的分支代码。
懒加载有两种实现方法:
方法一
在函数第一次调用时,对函数本身进行重写,该函数会被重写为符合分支条件的函数。
这样在后面的代码中,对原函数的调用就不用再执行if条件分支判断了, 我们可以用下面的方式使用惰性载入重写 addEvent()。
function addEvent (type, element, fun) {
if (element.addEventListener) {
addEvent = function (type, element, fun) {
element.addEventListener(type, fun, false);
}
} else if(element.attachEvent){
addEvent = function (type, element, fun) {
element.attachEvent('on' + type, fun);
}
} else{
addEvent = function (type, element, fun) {
element['on' + type] = fun;
}
}
return addEvent(type, element, fun);
}
在这种懒加载方法中,在 addEvent()函数 中,if 语句的每个分支都会为 addEvent 变量赋值,重写了原函数。在函数体的最后返回重写后的新函数。
下一次调用 addEvent() 的时候,便会直接调用新赋值的函数,不会再执行 if 语句了。
方法二
另一种懒加载的实现方法是在声明函数时就指定适当的函数。 这样在第一次调用函数时就不会损失性能了,只在代码加载时会损失一点性能。
var addEvent = (function () {
if (document.addEventListener) {
return function (type, element, fun) {
element.addEventListener(type, fun, false);
}
} else if (document.attachEvent) {
return function (type, element, fun) {
element.attachEvent('on' + type, fun);
}
}else {
return function (type, element, fun) {
element['on' + type] = fun;
}
}
})();
第二种放方法使用了函数表达式(用 var 声明函数)创建一个匿名的自执行函数,通过不同的分支以确定应该使用那个函数实现,每个分支都返回一个正确的函数,并立即将其赋值给变量 addEvent。
懒加载的优点在于只执行一次 if 分支,避免了函数每次执行时候都要执行 if 分支和不必要的代码,提升了代码性能。