什么是惰性函数?
先来看个例子
js
function addEvent(el, type, handler) {
if (window.addEventListener) {
el.addEventListener(type, handler, false);
} else {
el.attachEvent('on' + type, handler);
}
}
上面这段代码中,每次调用 addEvent
都会进行一遍判断。实际上,我们并不需要每次都进行判断,只需要执行一次就够了,当然,我们也可以存个全局的flag来记录,但是,有更好的办法了
js
function addEvent(el, type, handler) {
if (window.addEventListener) {
addEvent = function(el, type, handler) {
el.addEventListener(type, handler, false);
}
} else {
addEvent = function(el, type, handler) {
el.attachEvent('on' + type, handler);
}
}
return addEvent(el, type, handler); // 调用新的函数
}
这就是惰性函数:第一次执行时会根据条件覆盖自身,后续调用直接执行更新后的逻辑。
惰性函数的实现方式
惰性函数一般情况下有两种实现方式
在函数内部重写自身
这种实现方式就是上面我们介绍的那样
js
function foo() {
console.log('初始化...');
foo = function() {
console.log('后续逻辑');
}
}
大多数情况下,这种实现方式都可以覆盖
用函数表达式赋值
js
const foo = (function() {
if (someCondition) {
return function() { console.log('A'); }
} else {
return function() { console.log('B'); }
}
})();
这种情况适用于模块或者立即执行的情况,其实就是用闭包做了个封装
惰性函数的应用场景
兼容性判断
我们在做适配的时候,很多时候需要进行浏览器特性的判断,比如之前提到的事件绑定
性能优化
其实惰性函数说起来很像单例,他的原理就是只执行一次,那么如果想要避免一些重复操作,尤其是重复初始化,就可以想一下是不是可以用惰性函数来处理,比如Canvas渲染引擎,加载某些外部依赖、判断登录状态等等
注意事项
- 写好注释,一定要写好注释,因为函数在执行后会变化,不写注释如果除了一些问题,可能后面维护的人会骂街,会大大增加你的不可替代性,咳咳,千万不要这么操作,一定要写好注释
- 不适合频繁修改逻辑和复杂上下文的场景,会增加复杂度
一句话总结:能判断一次就不要判断两次,惰性函数让你的代码更聪明