利用函数的惰性载入提高javascript代码性能
假装有个需求
我们现在需要写一个 foo 函数,这个函数返回首次调用时的 Date 对象,注意是首次。
普通方法
1 | var t; |
问题有两个,一是污染了全局变量,二是每次调用 foo 的时候都需要进行一次判断。
首先解决污染全局变量的问题
1 | var foo = (function() { |
函数对象
1
2
3
4
5
6//函数也是一种对象,利用这个特性,我们也可以解决这个问题。
function foo() {
if (foo.t) return foo.t;
foo.t = new Date();
return foo.t;
}
不过依旧没有解决调用时都必须进行一次判断的问题。
解决的方案就是称之为惰性载入的技巧。
所谓惰性载入,就是说函数的if分支只会执行一次,之后调用函数时,直接进入所支持的分支代码。 有两种实现惰性载入的方式,第一种事函数在第一次调用时,对函数本身进行二次处理,该函数会被覆盖为符合分支条件的函数,这样对原函数的调用就不用再经过执行的分支了, 我们可以用下面的方式使用惰性载入重写 foo()
.
1 | var foo = function() { |
常见应用举例
在DOM 事件添加中,为了兼容现代浏览器和万恶的 IE 浏览器,我们需要对浏览器环境进行一次判断:
1 | function addEvent (type, el, fn) { |
每次调用 addEvent
函数的时候,它都要对浏览器所支持的能力进行检查,首先检查是否支持 addEventListener
方法,如果不支持,再检查是否支持 attachEvent
方法。 这个过程在 addEvent
函数每次调用的时候都要走一遍,其实,如果浏览器支持其中的一种方法,那么他就会一直支持了,就没有必要再进行其他分支的检测了, 也就是说,if
语句不必每次都执行,代码可以运行的更快一些。
1 | function addEvent (type, el, fn) { |
在这个惰性载入的 addEvent()
中,if
语句的每个分支都会为 addEvent
变量赋值,有效覆盖了原函数。 最后一步便是调用了新赋函数。下一次调用 addEvent()
的时候,便会直接调用新赋值的函数,这样就不用再执行 if
语句了。
上面这种方法会在函数第一次调用时损失一点性能,有可能造成用户第一次使用功能时产生卡顿.使用闭包可以解决这个问题.
1 | var addEvent = (function(){ |
虽然利用闭包在第一次调用函数时就不会损失性能了,但是会在代码加载时会损失一点性能。所以只能具体情况具体分析了.
利用函数的惰性载入提高javascript代码性能