举个小栗子来聊下性能优化

我向来是先实现功能再考虑优化,不然就本末倒置了。

网上有很多关于前端优化的帖子,最出名的应该是雅虎前端优化35条军规了,但其实很多朋友看完就忘了,确实要记住这么多条优化建议有困难。但你吸收这些优化建议后,你的潜意识就会慢慢养成优化的习惯,看到不完美的代码你就会不自觉的想到怎样去优化它们。

今天就举一个小栗子,我们来聊聊怎样做前端优化。

产品经理进门:“小周,这次的项目要兼容到IE8。”

我:“好的,没问题…”(除了这个我还能说什么?)

好了,假设不能使用第三方库,我们要用原生JS实现DOM元素事件绑定,我们就要考虑到兼容性问题(这时候脑子里面不用想优化的问题,先想想怎么实现功能吧)。

我最初可能会这么写:

1
2
3
4
5
6
7
8
var addEvent = function(elem, type, handler) {
if(window.addEventListener) {
return elem.addEventListener(type, handler, false);
}
if(window.attachEvent) {
return elem.attachEvent('on' + type, handler);
}
};

上面的代码没有问题,完美兼容到了IE8,功能算是实现了,这时候我们就要开始考虑性能优化的问题了。

先来看看这个函数有什么缺点,每次执行函数时都会进入if条件分支,虽然对于现代浏览器来说,执行这些分支开销很小,但就是这些细节,区分了优秀与平庸。

我们可以再想一个方案来让这个功能实现的更完美,我们把嗅探浏览器的操作提前到代码加载时执行,在代码加载时就进行判断,让addEvent返回一个包裹了一个正确逻辑的函数,这里可以用自执行函数来做。

1
2
3
4
5
6
7
8
9
10
11
12
var addEvent = (function() {
if(window.addEventListener) {
return function(elem, type, handler) {
elem.addEventListener(type, handler, false);
}
}
if (window.attachEvent) {
return function(elem, type, handler) {
elem.attachEvent('on' + type, handler);
}
}
})();

这样写仍然有个缺点,或许从头到尾我们都没有用过addEvent函数,那自执行函数中的浏览器嗅探完全是多余的,而且会延长页面ready的时间。

想想看还有什么方法可以优化首屏加载。

我们仍然把addEvent声明为一个普通函数,在函数中仍然有判断分支。但在第一次进入分支后,函数内部重写addEvent函数,从而得到我们所期望的addEvent函数,下次调用addEvent函数时,内部将不再进行分支判断:

1
2
3
4
5
6
7
8
9
10
11
12
var addEvent = function(elem, type, handler) {
if(window.addEventListener) {
addEvent = function(elem, type, handler) { //重写addEvent函数
elem.addEventListener(type, handler, false);
}
}else if(window.attachEvent) {
addEvent = function(elem, type, handler) {
elem.attachEvent('on' + type, handler);
}
}
addEvent(elem, type, handler);
}

回过头再对比最初的函数,发现其实优化也不是那么困难,最重要的时我们要养成优化代码的习惯,看到一段代码,就要开始思考有哪些可以改进的地方,如果你想要成为一名优秀的程序员,这一点是必不可少的,量变引发质变这个道理大家都懂。

如果你还没有养成这种习惯,那试着带着这种思维习惯去review自己的代码,你会发现,呵呵…

本文作者:余震(Freak)
本文出处:Rockjins Blog
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN许可协议。转载请注明出处!

坚持,您的支持将鼓励我继续爬下去!