3.6.4 避免with语句
和函数类似 ,with语句会创建自己的作用域,因此会增加其中执行的代码的作用域链的长度,由于额外的作用域链的查找,在with语句中执行的代码肯定会比外面执行的代码要慢,在能不使用with语句的时候尽量不要使用with语句。 例如:
with (a.b.c.d) { property1 = 1; property2 = 2; }
可以替换为: var obj = a.b.c.d; obj.property1 = 1; obj.property2 = 2;
3.6.5 类型转换
3.6.5.1 数字转换成字符串
一般最好用\来将数字转换成字符串,虽然看起来比较丑一点,但事实上这个效率是最高的,性能上来说:
(\
3.6.5.2 浮点数转换成整型
很多人喜欢使用parseInt(),其实parseInt()是用于将字符串转换成数字,而不是浮点数和整型之间的转换,我们应该使用Math.floor()或者Math.round()
3.6.5.3 自定义对象转换
如果定义了toString()方法来进行类型转换的话,推荐显式调用toString(),因为内部的操作在尝试所有可能性之后,会尝试对象的toString()方法尝试能否转化为String,所以直接调用这个方法效率会更高
14
上海天缘迪柯信息技术有限公司
3.6.6 最小化语句数
3.6.6.1 多个变量声明
在JavaScript中所有变量都可以使用单个var语句来声明,这样就是组合在一起的语句,以减少整个脚本的执行时间
3.6.6.2 插入迭代值
如var name=values[i]; i++;前面两条语句可以写成var name=values[i++]
3.6.6.3 使用直接量
var aTest = new Array();替换为var aTest =[]; var aTest = new Object;替换为var aTest ={}; var reg=new RegExp()替换为var reg = /../;
如果要创建具有一些特性的一般对象,也可以使用字面量,如下: var oFruit = new O; oFruit.color=\oFruit.name=\
前面的代码可用对象字面量来改写成这样: var oFruit = {color:\
3.6.7 优化DOM交互
因为DOM交互开销很大,所以需要限制DOM操作的次数
3.6.7.1 使用DocumentFragment优化多次append
一旦需要更新DOM,请考虑使用文档碎片来构建DOM结构,然后再将其添加到现存的文档中。
例如:
for (var i = 0; i < 1000; i++) { var el = document.createElement('p');
15
el.innerHTML = i;
document.body.appendChild(el); }
可以替换为:
var frag = document.createDocumentFragment(); for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el); }
document.body.appendChild(frag);
3.6.7.2 使用一次innerHTML赋值代替构建dom元素
对于大的DOM更改,使用innerHTML要比使用标准的DOM方法创建同样的DOM结构快得多。
例如:
var frag = document.createDocumentFragment(); for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el); }
document.body.appendChild(frag); 可以替换为: var html = [];
for (var i = 0; i < 1000; i++) { html.push('
' + i + '
'); }document.body.innerHTML = html.join('');
3.6.7.3 通过模板元素clone,替代createElement
很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效
16
上海天缘迪柯信息技术有限公司
率较低,如果需要直接插入HTML,可以找一个容器元素,比如指定一个div或者span,并设置他们的innerHTML来将自己的HTML代码插入到页面中。通常我们可能会使用字符串直接写HTML来创建节点,其实这样做,1无法保证代码的有效性2字符串操作效率低,所以应该是用document.createElement()方法,而如果文档中存在现成的样板节点,应该是用cloneNode()方法,因为使用createElement()方法之后,你需要设置多次元素的属性,使用cloneNode()则可以减少属性的设置次数——同样如果需要创建很多元素,应该先准备一个样板节点。
例如:
var frag = document.createDocumentFragment(); for (var i = 0; i < 1000; i++) { var el = document.createElement('p'); el.innerHTML = i; frag.appendChild(el); }
document.body.appendChild(frag); 替换为:
var frag = document.createDocumentFragment(); var pEl = document.getElementsByTagName('p')[0]; for (var i = 0; i < 1000; i++) { var el = pEl.cloneNode(false); el.innerHTML = i; frag.appendChild(el); }
document.body.appendChild(frag);
3.6.7.4 使用firstChild和nextSibling代替childNodes遍历dom元素
例如:
var nodes = element.childNodes;
for (var i = 0, l = nodes.length; i < l; i++) { var node = nodes[i]; ?? }
可以替换为:
var node = element.firstChild; while (node) {
17
??
node = node.nextSibling; }
3.6.7.5 删除DOM节点
删除dom节点之前,一定要删除注册在该节点上的事件,不管是用observe方式还是用attachEvent方式注册的事件,否则将会产生无法回收的内存。另外,在removeChild和innerHTML=’’二者之间,尽量选择后者. 因为在sIEve(内存泄露监测工具)中监测的结果是用removeChild无法有效地释放dom节点
3.6.7.6 使用事件代理
任何可以冒泡的事件都不仅仅可以在事件目标上进行处理,目标的任何祖先节点上也能处理,使用这个知识就可以将事件处理程序附加到更高的地方负责多个目标的事件处理,同样,对于内容动态增加并且子节点都需要相同的事件处理函数的情况,可以把事件注册提到父节点上,这样就不需要为每个子节点注册事件监听了。另外,现有的js库都采用observe方式来创建事件监听,其实现上隔离了dom对象和事件处理函数之间的循环引用,所以应该尽量采用这种方式来创建事件监听
3.6.7.7 重复使用的调用结果,事先保存到局部变量
避免多次取值的调用开销 例如:
var h1 = element1.clientHeight + num1; var h2 = element1.clientHeight + num2; 可以替换为:
var eleHeight = element1.clientHeight; var h1 = eleHeight + num1; var h2 = eleHeight + num2;
3.6.7.8 注意NodeList
最小化访问NodeList的次数可以极大的改进脚本的性能。如
18