惰性函数和普通函数的区别是它的执行分支只在函数调用时执行一次,调用过程中函数会被另一种合适的执行方式覆盖,所以后面再调用这个函数时,就不会再执行分支语句。
使用场景
为了兼容各大浏览器,经常会在函数内部写大量if语句来检侧浏览器特性。比如为dom节点添加事件函数。
function addEvent(type, element, fn) {
if(element.addEventListener) {
element.addEventListener(type, fn, false)
}
else if(element.attachEvent){
element.attachEvent('on' + type, fn);
}
else{
element['on' + type] = fn;
}
}
上面的函数会在每次执行点击事件时,都进行浏览器能力检侧,理论上只要检测一次就知道支持哪个方法了,后面的点击事件不需要再执行一遍判断,下面改写一下。
惰性函数
在使用惰性函数重写上面的addEvent之前,先了解一下函数的重写:
function foo(){
console.log(1)
foo = function() {
console.log(2)
}
}
当第一次调用foo函数时,会打印1,然后函数会被覆盖掉。当第二次及以后调用时,会打印2。这就实现了函数的重写。
【addEvent()重写】
function addEvent(type, element, fn) {
if(element.addEventListener) {
addEvent = function(type, element, fn) {
element.addEventListener(type, fn, false)
}
}
else if(element.attachEvent){
addEvent = function(type, element, fn) {
element.attachEvent('on' + type, fn);
}
}
else{
addEvent = function(type, element, fn) {
element['on' + type] = fn;
}
}
return addEvent(type, element, fn);
}
当第一次调用addEvent函数时,会执行分支判断,新的函数覆盖掉原来的addEvent,以后再调用时执行的就是覆盖后的函数。
上面的函数有一个小问题,如果addEvent函数名称变化,内部的函数名要一起修改,这就比较麻烦。下面改写一下addEvent,把嗅探浏览器的操作函数提前执行,并返回一个包含了正确逻辑的函数。
var addEvent = (function () {
if (document.addEventListener) {
return function (type, element, fn) {
element.addEventListener(type, fn, false);
}
}
else if (document.attachEvent) {
return function (type, element, fn) {
element.attachEvent('on' + type, fn);
}
}
else {
return function (type, element, fn) {
element['on' + type] = fn;
}
}
})();