Home  >  Article  >  Web Front-end  >  Summary of tips on how to improve JavaScript Web performance

Summary of tips on how to improve JavaScript Web performance

伊谢尔伦
伊谢尔伦Original
2017-07-20 10:22:031091browse

Javascript performance optimization is by no means a written technique. Nicholas's technical evolution lists 10 suggestions to help you write efficient JS code

1. Define local variables

When a variable is referenced, JavaScript will look for the variable in different members of the scope chain. The scope chain refers to the set of available variables currently acting on it. It contains at least two parts in various mainstream browsers: the set of local variables and the set of global variables.

Simply put, the deeper the JavaScript engine searches in the scope chain, the more time the operation will take. The engine first looks for local variables starting from this, then function parameters, locally defined variables, and finally iterates through all global variables.

Because local variables are at the beginning of this chain, it is always easier to find local variables than to find global variables. So when you want to use a global variable more than once, you should define it as a local variable, like this:


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

rewritten as


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

2. Do not use the with() statement

This is because the with() statement will add additional scope at the beginning of the scope chain variable. The extra variables mean that when any variable needs to be accessed, the JavaScript engine needs to scan the variables generated by the with() statement first, then the local variables, and finally the global variables.
So with() essentially gives local variables all the performance drawbacks of global ones, and in turn derails Javascript optimization. Performance plans go bust.

3. Use closures with care

Although you may not know "closures" yet, you may be using this technique often without realizing it. Closures are basically considered new in JavaScript. When we define an immediate function, we use closures, such as:

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

The problem with closures is that by definition, in their role There are at least three objects in the domain chain: closure variables, local variables and global variables. These extra objects will cause the performance issues mentioned in suggestions 1 and 2.

But I think Nicholas is not asking us to stop eating because of choking. Closures are still very useful for improving code readability, etc., just don't abuse them (especially in loops).

4. Object properties and array elements are slower than variables

When it comes to JavaScript data, generally speaking, there are 4 access methods: numerical values, variables, Object properties and array elements. When considering optimizations, numbers and variables perform about the same, and are significantly faster than object properties and array elements.
So when you reference an object property or array element multiple times, you can get performance improvements by defining a variable. (This rule is valid when reading and writing data)
Although this rule is correct in most cases, Firefox has done some interesting work in optimizing array indexes, which can make its actual performance better than variable. However, considering the performance drawbacks of array elements on other browsers, you should try to avoid array searches unless you really only develop for the performance of Firefox.

5. Don’t dig too deep into the array

Also, programmers should avoid digging too deep into the array because the more layers you enter, the The operation speed is slower.
Simply put, operations in arrays nested with many levels are slow because the search speed of array elements is very slow. Imagine that if you operate on array elements nested three levels, you have to perform three array element searches instead of one.
So if you keep referencing foo.bar, you can improve performance by defining var bar = foo.bar.

6. Avoid for-in loops (and function-based iteration)

Here's another piece of very dogmatic advice: Don't use for-in loops.
The logic behind this is very straightforward: to iterate over the elements in a collection, you can use a for loop, or a do-while loop instead of a for-in loop. A for-in loop may not only need to traverse additional array items , more time is needed.
In order to iterate over these elements, JavaScript needs to create a function for each element. This function-based iteration brings a series of performance problems: the additional functions introduce the context in which the function object is created and destroyed, which will be in effect Additional elements are added to the top of the domain chain.

7. Combine control conditions and control variables when looping

When it comes to performance, the work that needs to be avoided in loops has always been a hot topic, because loops will Repeatedly executed many times. Therefore, if there is a need for performance optimization, the most obvious performance improvement may be obtained by operating on the loop first.
One way to optimize a loop is to combine the control conditions and control variables when defining the loop. The following is an example of not merging them:

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

When we add something to this loop, we find that there are several operations that will appear in each iteration. JavaScript engine requires:

#1:检查 x 是否存在
#2:检查 x 是否小于 0 (译者注:我猜这里是作者的笔误)
#3:使 x 增加 1

然而如果你只是迭代元素中的一些元素,那么你可以使用while循环进行轮转来替代上面这种操作:


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

如果你想更深入地了解循环的性能,Zakas提供了一种高级的循环优化技巧,使用异步进行循环(碉堡了!)

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

JavaScript使用了大量的HTML集合对象,比如 document.forms,document.images 等等。通常他们被诸如 getElementsByTagName、getElementByClassName 等方法调用。

由于大量的DOM selection操作,HTML集合对象相当的慢,而且还会带来很多额外的问题。正如DOM标准中所定义的那样:“HTML集合是一个虚拟存在,意味着当底层文档被改变时,它们将自动更新。”这太可怕了!

尽管集合对象看起来跟数组很像,他们在某些地方却区别很大,比如对于特定查询的结果。当对象被访问进行读写时,查询需要重新执行来更新所有与对象相关的组分,比如 length。

HTML集合对象也非常的慢,Nicholas说好像在看球的时候对一个小动作进行60倍速慢放。另外,集合对象也有可能造成死循环,比如下面的例子:


var ps = document.getElementsByTagName(&#39;p&#39;);
 
for (var i=0; i < ps.length; i++ ) {
  var p = document.createElement("p"); 
  document.appendChild(p);
}

这段代码造成了死循环,因为 ps 表示一个实时的HTML集合,并不是你所期望的数组。这种实时的集合在添加 e388a4556c0f65e1904146cc1a846bee 标签时被更新,所以i < p.length 永远都不会结束。

解决这个问题的方法是将这些元素定义成数组,相比只设置 var ps = document.getElementsByTagName(‘p') 稍微有点麻烦,下面是Zakas提供的强制使用数组的代码:


function array(items) {
  try {
    return Array.prototype.concat.call(items);
  } catch (ex) {
 
    var i    = 0,
      len   = items.length,
      result = Array(len);
 
    while (i < len) {
      result[i] = items[i];
      i++;
    }
 
    return result;
  }
}
 
var ps = array( document.getElementsByTagName(&#39;p&#39;) );
 
for (var i=0l i < ps.length; i++ ) {
  var p = document.createElement("p"); 
  document.appendChild(p);
}

9. 不要碰DOM!

不使用DOM是JavaScript优化中另一个很大的话题。经典的例子是添加一系列的列表项:如果你把每个列表项分别加到DOM中,肯定会比一次性加入所有列表项到DOM中要慢。这是因为DOM操作开销很大。
Zakas对这个进行了细致的讲解,解释了由于回流(reflow)的存在,DOM操作是非常消耗资源的。回流通常被理解为浏览器重新选渲染DOM树的处理过程。比如说,如果你用JavaScript语句改变了一个p的宽度,浏览器需要重绘页面来适应变化。
任何时候只要有元素被添加到DOM树或者从DOM树移除,都会引发回流。使用一个非常方便的JavaScript对象可以解决这个问题——documentFragment,我并没有使用过,但是在Steve Souders也表示同意这种做法之后我感觉更加肯定了。
DocumentFragment 基本上是一种浏览器以非可视方式实现的类似文档的片段,非可视化的表现形式带来了很多优点,最主要的是你可以在 documentFragment 中添加任何结点而不会引起浏览器回流。

10. 修改CSS类,而不是样式

你也许听说过:修改CSS类必直接修改样式会更高效。这归结于回流带来的另一个问题:当布局样式发生改变时,会引发回流。
布局样式意味着任何影响改变布局的变化都会强制引起浏览器回流。比如宽度、高度、字号、浮动等。
但是别误会我的意思,CSS类并不会避免回流,但是可以将它的影响最小化。相比每次修改样式都会引起回流,使用CSS类一次修改多个样式,只需要承担一次回流带来的消耗。
因此在修改多个布局样式的时候,使用CSS类来优化性能是明智的选择。另外如果你需要在运行时定义很多歌CSS类,在DOM上添加样式结点也是不错的选择。

The above is the detailed content of Summary of tips on how to improve JavaScript Web performance. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn