ES 编码实践 —— 惰性载入函数
published
惰性载入函数能够避免执行不必要的代码。
假设,现在到了一个新的时代,人人都开始用 ES 削铅笔,由于这个需求很旺盛,各大引擎都准备添加这个功能。但是还没有统一的标准,所以各大引擎的实现也千差万别。这就苦了程序员,为了编写出通用的削铅笔代码,必须对各个引擎的功能支持情况进行判断。 假设,现在有两个引擎,对削铅笔的功能提供了支持:
-
eco 引擎,支持削铅笔功能的对象的构造函数是
ecoSP
-
mca 引擎,支持削铅笔功能的对象的构造函数是
mcaSP
现在来编写代码:
function createSP() {
if (typeof ecoSP !== 'undefined') {
return new ecoSP()
} else if (typeof mcaSP !== 'undefined') {
return new mcaSP()
} else {
throw new Error('No SP object available.')
}
}
上面的代码,每次调用 createSP()
的时候,它都要对引擎进行检测 —— 先检测是不是 eco 引擎,再检测是不是 mca 引擎,如果都不是就抛出一个错误。这看起来没啥问题,但是代码在某一个引擎下执行,肯定都只会执行 if
语句的某一个分支。试想,如果代码运行在 eco 引擎下,每次都进行这种判断,不是挺蠢的嘛。如果 if
语句不必每次执行就好了,代码可以运行得更快点。解决的方案就是 惰性载入函数。 惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方法:
- 在第一次调用时,根据情况覆写函数
- 在声明函数时,就指定适当的函数(与 1 相比,在第一次调用函数时不会损失性能,但是在代码首次加载时会损失性能)
function createSP() {
if (typeof ecoSP !== 'undefined') {
createSP = function () {
return new ecoSP()
}
} else if (typeof mcaSP !== 'undefined') {
createSP = function () {
return new mcaSP()
}
} else {
createSP = function () {
throw new Error('No SP object available.')
}
}
return createSP()
}
在这个惰性载入的 createSP()
中,if
语句的每一个分支都会为 createSP
变量赋值,这样会覆盖原有的函数定义,最后再调用新的函数。等到下一次再调用 createSP()
的时候,就会直接调用新的函数,这样就不用再次执行 if
语句了。
var createSP = (function () {
if (typeof ecoSP !== 'undefined') {
return function () {
return new ecoSP()
}
} else if (typeof mcaSP !== 'undefined') {
return function () {
return new mcaSP()
}
} else {
return function () {
throw new Error('No SP object available.');
}
}
})()
这里创建了一个 IIFE。每个分支都返回合适的函数定义,以便立即执行后赋值给 createSP
。