JavaScript,js培训班
您的位置: 主页 > web前端文章 > javascript >

JavaScript性能提升技巧【访问量:58】

1.定义局部变量

当引用一个变量时,Javascript通过循环遍历作用域链的不同成员来捕获它。此作用域链是当前作用域内可用变量的集合,并且在所有主要浏览器中至少有两个项目:一组局部变量和一组全局变量。

简而言之,引擎越深入挖掘该范围链,操作时间就越长。它首先检查局部变量this,函数参数,然后是任何本地定义的变量,然后遍历任何全局变量。

由于局部变量是这个链中的第一个,它们总是比全局变量更快。因此,无论何时,您多次使用全局变量,都应该在本地重新定义它,例如更改:

var blah=document.getElementById('myID'),
blah2=document.getElementById('myID2');
至:
var doc=document,
blah=doc.getElementById('myID'),
blah2=doc.getElementById('myID2');

2.不要使用该with()陈述

这几乎是一个事实:with()声明是纯粹的Javascript邪恶。

这是因为with()在上述范围链的开头附加了一组额外的变量。这个额外的项目意味着任何时候调用任何变量时,JavaScript引擎都必须遍历with()变量,然后是局部变量,然后遍历全局变量。

所以with()本质上给了全局变量的所有性能缺陷,并反过来影响了JavaScript优化。

3.谨慎使用闭包

闭包是Javascript的一个非常强大和有用的方面,但它们带有自己的性能缺陷。

虽然你可能不知道“闭包”这个词,但你可能经常使用它们。闭包基本上可以被认为是newJavascript中的,我们在每次定义一个函数时都使用一个闭包,例如:

document.getElementById('foo').onclick=function(ev){};

闭包的问题是,根据定义,它们的作用域链中至少有三个对象:闭包变量局部变量和全局变量。这些额外的项目导致我们在技巧#1和#2中一直避免的所有性能问题。

但我不认为尼古拉斯希望我们把宝宝扔出去洗澡。为了方便和使代码更具可读性,闭包仍然很有用,只是尽量不要过度使用它们(特别是不能在循环中使用)。

4.对象属性和数组项比变量慢

当谈到Javascript数据时,几乎有四种方法可以访问它:文字值,变量,对象属性和数组项。在考虑优化时,文字值和变量的表现大致相同,并且明显快于对象属性和数组项。

因此,无论何时多次引用对象属性或数组项,都可以通过定义变量来提高性能。(这适用于读取和写入数据。)

虽然这个规则基本上是正确的,但Firefox已经做了一些有趣的事情来优化数组索引,并且实际上对数组项的性能比变量要好。但是其他浏览器中的数组项的性能缺点意味着您应该仍然避免数组查找,除非您确实只针对Firefox性能。

5.不要深入阵列

另外,你应该避免深入挖掘数组。这是因为你挖的越深,操作越慢。

简单地说,深入挖掘数组很慢,因为数组项查找速度慢。想一想:如果你将三个层次挖掘到一个数组中,那就是三个数组项查找,而不是一个。

所以如果你经常参考,foo.bar你可以通过定义来提升性能varbar=foo.bar;。

6.避免for-in循环(和基于函数的迭代)

这是另一个非常黑白的性能提示:不要使用for-in循环。

这背后的逻辑非常简单:不像循环遍历一组索引,就像使用afor或a循环一样do-while,for-in不仅可能循环通过其他数组项,还需要更多努力。

为了遍历这些项目,Javascript必须为每个项目设置一个函数。这种基于功能的迭代带来了一系列性能问题:引入了一个额外的函数,并创建并销毁了相应的执行上下文,最后在该范围链中添加了一个附加对象。

7.使用循环时结合控制条件和控制变量更改

无论何时谈论性能,在循环中避免工作都是一个热门话题,因为很简单,循环会一遍又一遍地重复。所以如果有任何性能提升,你很可能会看到你的循环中最大的提升。

利用这一点的一种方法是在定义循环时将控制条件和控制变量结合起来。以下是一个不包含这些控件的示例:

for(var x=0;x<10;x++){
};

在我们为这个循环添加任何东西之前,每次迭代都会发生一些操作。Javascript引擎必须#1测试是否x存在,#2测试如果x<0和#3添加增量x++。

但是,如果您只是迭代数组中的某些项目,则可以通过翻转此迭代并使用while循环来删除其中的一个操作:

var x=9;
do{}while(x--);

如果你想将循环性能提升到一个新的水平,Zakas还提供了一种更先进的循环优化技术,它可以异步运行(非常酷!)循环。

8.为HTML集合对象定义数组

Javascript使用了许多HTML集合对象,如document.forms。document.images等等。另外这些通过诸如getElementsByTagName和的方法调用getElementsByClassName。

与任何DOM选择一样,HTML收集对象相当慢,但也带来了其他问题。正如DOM级别1规范所述,“HTMLDOM中的集合被假定为实时的,这意味着它们在底层文档发生更改时会自动更新”。

这太可怕了。

尽管集合对象看起来像数组,但它们却完全不同:特定查询的结果。无论何时读取或写入该对象时,都必须重新运行此查询,其中包括更新对象的所有外围方面,如其对象length。

HTML集合对象非常慢;尼古拉斯在一次小型手术中提到了慢60倍的指标。此外,这些集合对象可能会导致无法预期的无限循环。例如:

var divs=document.getElementsByTagName('div');
for(vari=0li<divs.length;i++){
var div=document.createElement("div");
document.appendChild(div);
}

这会导致无限循环,因为它divs表示一个实时的HTML集合,而不是像您期望的那样的数组。每当我们向DOM追加新内容时,此实时集合都会更新,因此i<divs.length永远不会终止。

解决这个问题的方法是将这些项目定义在一个数组中,这比仅仅设置更复杂一些vardivs=document.getElementsByTagName('div');。这是Zakas用来强制数组的脚本:

function array(items){
try{
   returnArray.prototype.concat.call(items);
}catch(ex){
var i=0,
len=items.length,
result=Array(len);
while(i<len){
result[i]=items[i];
i++;
}
   returnresult;
}
}
var divs=array(document.getElementsByTagName('div'));
for(vari=0li<divs.length;i++){
 var div=document.createElement("div");
 document.appendChild(div);
}

9.停止触摸DOM,该死!

离开DOM单独是Javascript优化中的另一个主题。典型的例子是追加一个列表项的数组:如果你将它们分别附加到DOM中,那么它比一次追加它们要慢很多。这是因为DOM操作很昂贵。

Zakas详细介绍了这一点,并解释说由于回流,DOM操作资源非常大。回流基本上是浏览器在屏幕上重新呈现DOM元素的过程。例如,如果您使用Javascript更改div的宽度,浏览器必须刷新呈现的页面才能解决此更改。

任何时候元素被添加或从DOM中删除,都会发生回流。这个解决方案是一个非常方便的Javascript对象,documentFragment在SteveSouders承认这一点后,我觉得没有用过它。

DocumentFragment基本上是一个类似文档的片段,不会被浏览器直观地表示。没有视觉表示提供了许多优点;主要是您可以将节点附加到documentFragment而不会导致任何浏览器重排。

10.更改CSS类不是样式

您可能已经听说,更改CSS类比更改样式更优化。这归结为另一个回流问题:只要布局样式发生更改,就会发生回流。

布局样式意味着任何可能影响布局并强制浏览器回流的内容。例如,width,height,font-size,float,等。

现在不要误解我的意思,CSS类不会避免回流,他们只是最小化它。每次更改给定样式时,您都可以使用CSS类来一次更改多种样式,而不是只发生一次回流,而不是每次更改给定样式都会产生回流损失。

因此,无论何时改变多个布局样式,都可以使用CSS类名。此外,如果您需要定义多个类,则最好将样式节点追加到DOM。

当然上面这些内容还算完整,如果想学习更多可以报js培训班


2018-04-03
上一篇:没有了
匿名评论