##《高性能网站建设进阶指南》知识摘录 现在,许多网站和项目的整个用户界面都是用JavaScript来实现的,因此若是对JavaScript进行优化,或许对网站的性能提高会有所帮助,下面介绍几种编写高效JavaScript的方法javascript
###使用局部对象 当执行JavaScript代码时,JavaScript引擎会建立一个执行上下文,当页面加载时,JavaScript引擎也会在页面加载后建立一个全局的执行上下文。每一个执行上下文都有一个与之关联的做用链域,用于解析标识符。全局执行上下文的做用链域中只有一个变量对象,它定义了JavaScript中全部可用的全局对象和函数,当函数被建立(不是执行)时,JavaScript引擎会把建立时执行上下文的做用链域赋给函数的内部属性[scope]
,而后,当函数被执行时,JavaScript引擎会建立一个活动对象,并在初始化时给this
,arguments
,命名参数和该函数的全部局部变量赋值。java
JavaScript引擎在解析标识符的时候,它首先查找从做用链中的第一个对象开始,这个对象就是包含该函数局部变量的活动对象。若是在该对象中没有找到标识符,就会继续在做用链域中的下一个对象里查找标识符,一旦找到标识符,查找就结束。数组
到目前为止,局部变量是JavaScript中读写最快的标志符,由于它们存在于执行函数的活动对象中,解析标识符只须要查找做用链域中的单个对象,读取变量值的总耗时随着查找做用链域的逐层深刻而不断增加,因此标识符越深存取速度越慢。以下代码所示:浏览器
function createChildFor(eleId){ var ele = document.getElementById(eleId), newEl = document.createElement('div'); element.appendChild(newEl); }
在上面这段代码中,这个函数引用了两次全局变量document
,由于document
使用超过了一次,因此咱们能够改进为以下代码:数据结构
function createChildFor(eleId){ var doc = document, var ele = doc.getElementById(eleId), newEl = doc.createElement('div'); element.appendChild(newEl); }
###避免增加做用链域 在代码执行过程当中,执行上下文对应的做用域链一般保持不变,然而有两个语句会临时增长执行上下文的做用链域,以下面的代码:app
var person = { name:'sunshine', age:99 }; function displayInfo(){ var count = 5; with(person){ alert(count); } }
如上所示,person对象传入了with语句块,这样就能够像访问局部变量同样访问name
和age
属性了。实际上它是将一个新的变量对象添加到执行上下文做用域的顶部 函数
这样你在访问内部变量count
的时候,它的访问层级也会相应变深,因此性能就会降低性能
第二个会增加做用链域的是try-catch
语句块中的catch
从句。在执行catch
从句中的代码时,其行为方式相似于with
语句,也就是在做用链域的顶部增长了一个对象,该对象包含了由catch
指定命名的异常对象,然而,因为catch
从句仅在执行try
从句发生错误时才执行,因此它比with
语句的影响要小。优化
###高效的数据存储 通常而言,在脚本中有4种地方能够存取数据:网站
- 字面量值
- 变量
- 数组元素
- 对象属性
在大多数浏览器中,从字面量中读取值和从局部变量中读取值得开销差别很小,真正的差别在于从数组或者对象中读取数据,存取这些数据结构中的某个值,以下代码所示:
function fun(data){ if(data.count > 0){ for(var i = 0;i<data.count;i++){ //do somethine } } }
将上面那段代码改写成以下所示:
示:
function fun(data){ var count = count; //将对象的属性存在变量字面量中 if(count > 0){ for(var i = 0;i<count;i++){ //do somethine } } }
下面这段代码,就会直接去读取count字面量的值,而不是再去读取对象的属性值,这样在性能上也有所提高。同理可得:存取data.count
笔data.item.count
快
###快速条件判断 在条件有不少的状况下,究竟是使用if-else
仍是switch
,if-else
和switch
的结构相信你们都已经很熟悉了,在这里我就再也不赘述了,下面还提供一种方法,数组查询方法
var results = [result0,result1,result2,result3,result4,result5]; return results[value];
下面就这三种方法给出一种统一的选择方案:
- 使用
if
语句的状况 ---两个以内的离散值须要判断 ---大量的值能容易地等到不一样的区间范围中- 使用
switch
语句的状况 --- 超过两个而少于10个离散值须要判断 ---条件是非线性的,没法分理出区间范围- 使用数组查询的状况 ---超过10个值须要判断 ---条件对应的结果使单一值,而不是一系列操做
###快速循环 在JavaScript中,循环是致使性能问题的常见缘由,因此下面从以下几个方面进行优化循环
####将循环次数存放在变量中
var value = [1,2,3,4,5]; var len = value.length; for(var i=0;i<len;i++){ //do something }
####转换行为的方式 将上面的代码改写成以下所示:
var value = [1,2,3,4,5]; var len = value.length; for(var i = len;i--;){ //do something }
由于结束条件变为与0进行比较,因此每一个循环的速度更快了。此时,for,while,do-while
的速度都是差很少的
####避免for-in循环 for循环的另外一宗变化是for-in循环,它是用来遍历javascript对象的可枚举属性的,典型的用法以下:
for(var prop in object){ if(object.hasOwnProperty(prop)){ // do something } }
for-in循环一般比其余循环慢,由于它须要从一个特定的对象中解析每一个可枚举属性,反过来讲,这意味着它为了提取这些属性须要检查对象的原型和整个原型链。遍历原型链就像遍历做用链域,他会增长好事,从而下降整个循环的性能
###避免运行过长的脚本
###谨慎使用HTMLCollection对象 每次存取这类对象的属性,都会从新查询DOM中匹配的节点,为了不这种昂贵的开销,只有在必要时才存取HTMLCollection对象,并将常常存取的值存储在局部变量中