0 Comments

改善用户体验 Web前端优化策略总结(2)

发布于:2013-07-01  |   作者:广州网站建设  |   已聚集:人围观

二、代码级优化

1. Javascript

(1). DOM

DOM操作应该是脚本中最耗性能的一类操作,例如增加、修改、删除DOM元素或者对DOM集合进行操作。如果脚本中包含了大量的DOM操作则需要注意以下几点:
广州网站建设,网站建设,广州网页设计,广州网站设计

a. HTML Collection

在脚本中document.images、document.forms、getElementsByTagName()返回的都是HTMLCollection类型的集合,在平时使用的时候大多将它作为数组来使用,因为它有length属性,也可以使用索引访问每一个元素。不过在访问性能上则比数组要差很多,原因是这个集合并不是一个静态的结果,它表示的仅仅是一个特定的查询,每次访问该集合时都会重新执行这个查询从而更新查询结果。所谓的“访问集合”包括读取集合的length属性、访问集合中的元素。

因此,当你需要遍历HTML Collection的时候,尽量将它转为数组后再访问,以提高性能。即使不转换为数组,也请尽可能少的访问它,例如在遍历的时候可以将length属性、成员保存到局部变量后再使用局部变量。

b. Reflow & Repaint

除了上面一点之外,DOM操作还需要考虑浏览器的Reflow和Repaint,因为这些都是需要消耗资源的。

(2). 慎用with

with(obj){ p = 1}; 代码块的行为实际上是修改了代码块中的执行环境,将obj放在了其作用域链的最前端,在with代码块中访问非局部变量是都是先从obj上开始查找,如果没有再依次按作用域链向上查找,因此使用with相当于增加了作用域链长度。而每次查找作用域链都是要消耗时间的,过长的作用域链会导致查找性能下降。因此,除非你能肯定在with代码中只访问obj中的属性,否则慎用with,替代的可以使用局部变量缓存需要访问的属性。  

(3). 避免使用eval和Function

每次 eval 或 Function 构造函数作用于字符串表示的源代码时,脚本引擎都需要将源代码转换成可执行代码。这是很消耗资源的操作 —— 通常比简单的函数调用慢100倍以上。

eval函数效率特别低,由于事先无法知晓传给 eval 的字符串中的内容,eval在其上下文中解释要处理的代码,也就是说编译器无法优化上下文,因此只能有浏览器在运行时解释代码。这对性能影响很大。

Function 构造函数比eval略好,因为使用此代码不会影响周围代码;但其速度仍很慢。此外,使用eval和Function也不利于Javascript压缩工具执行压缩。

(4). 减少作用域链查找

前文谈到了作用域链查找问题,这一点在循环中是尤其需要注意的问题。如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的。


  1. 低效率的写法:  
  2.  
  3. //全局变量  
  4. var globalVar = 1;  
  5. function myCallback(info){  
  6. for( var i = 100000; i--;){  
  7. //每次访问globalVar都需要查找到作用域链最顶端,本例中需要访问100000次  
  8. globalVar += i;  
  9.    }  

  1. 更高效的写法:  
  2.  
  3. //全局变量  
  4. var globalVar = 1;  
  5. function myCallback(info){  
  6.  
  7.    //局部变量缓存全局变量  
  8.  
  9.    var localVar = globalVar;  
  10.  
  11.    for( var i = 100000; i--;){  
  12.  
  13.   //访问局部变量是最快的  
  14.  
  15.   localVar += i;  
  16.  
  17.    }  
  18.  
  19.    //本例中只需要访问2次全局变量  
  20.  
  21.    globalVar = localVar;  
  22.  

此外,要减少作用域链查找还应该减少闭包的使用。

(5). 数据访问

Javascript中的数据访问包括直接量(字符串、正则表达式)、变量、对象属性以及数组,其中对直接量和局部变量的访问是最快的,对对象属性以及数组的访问需要更大的开销。当出现以下情况时,建议将数据放入局部变量:

a. 对任何对象属性的访问超过1次

b. 对任何数组成员的访问次数超过1次

另外,还应当尽可能的减少对对象以及数组深度查找。
广州网站建设,网站建设,广州网页设计,广州网站设计

(6). 字符串拼接

在Javascript中使用"+"号来拼接字符串效率是比较低的,因为每次运行都会开辟新的内存并生成新的字符串变量,然后将拼接结果赋值给新变量。与之相比更为高效的做法是使用数组的join方法,即将需要拼接的字符串放在数组中最后调用其join方法得到结果。不过由于使用数组也有一定的开销,因此当需要拼接的字符串较多的时候可以考虑用此方法。

2. CSS选择符

在大多数人的观念中,都觉得浏览器对CSS选择符的解析式从左往右进行的,例如


  1. #toc A { color: #444; } 
  2.  

这样一个选择符,如果是从右往左解析则效率会很高,因为第一个ID选择基本上就把查找的范围限定了,但实际上浏览器对选择符的解析是从右往左进行的。如上面的选择符,浏览器必须遍历查找每一个A标签的祖先节点,效率并不像之前想象的那样高。根据浏览器的这一行为特点,在写选择符的时候需要注意很多事项,有人已经一一列举了,详情参考此处。

3. HTML

对HTML本身的优化现如今也越来越多的受人关注了。

4. Image压缩

图片压缩是个技术活,不过现如今这方面的工具也非常多,压缩之后往往能带来不错的效果,具体的压缩原理以及方法在《Even Faster Web Sites》第10章有很详细的介绍,有兴趣的可以去看看。

标签:
飞机