Implementation method and advantages of JS performance optimization

  • 2021-08-10 06:30:37
  • OfStack

Recently, I just finished reading "High Performance javascript" and want to talk about the performance optimization of js. There are some differences in understanding, and you may need a lot of reminders.

Needless to say, the mention of javascript is inevitably associated with the Document Object Model (DOM), which acts as the program interface (API) of XML and HTML documents, is located in the browser, and is mainly used to deal with HTML documents. Also used in the Web program to get the XML document and use DOM API to access the data in the document. Although DOM is a language-independent API, its interface in the browser is implemented using javascript. Client-side scripting mostly deals with the underlying documentation (underlying document), and DOM is now an important part of javascript programming.

Browsers usually implement DOM and js independently. For example, in IE, the implementation of javascript is called Jscript, which is located in jscript. dll file. The implementation of DOM exists in another library called mshtml. dll (internally called Trident). This separation allows other technologies and languages, such as VBScript, to share the rendering functions provided by DOM and Trident. The DOM in Safari and the rendering use the WebCode implementation in Webkit, and the javascript part is implemented by a stand-alone javascriptCode engine (the latest version is named SquirrelFish). Google Chrome also uses the WebCore library in WebKit to render pages, but the javascript engine is developed by themselves and is called V8. The javascript engine of Firefox is named SpiderMonkey (the latest version is named TraceMonkey), which is independent of the rendering engine named Gecko.

Think of DOM and javascript (ECMAScript here, ECMAScript version used by JavaScript is ECMAScript-262) as an island, which are connected by toll bridges. Every time ECMAScript visits DOM, it needs to pass through this bridge and pay a "bridge crossing fee". The more times you visit DOM, the higher the cost. Therefore, finding ways to reduce the number of crossings can reduce the cost.

1. Overload transportation

As mentioned above, "bridge crossing fee" is very expensive, so we try our best to integrate it into one when we need to visit DOM many times. For example, the simplest example:


function innerHTMLLoop(){
   for(var count = 0;count < 15000 ;count++){
      document.getElementById('here').innerHTML +='a';
  } 
}

This function loops to modify the contents of page elements. There is a circular iteration in this code, and the element is accessed twice, once to read the innerHTML attribute value, and once to rewrite it. (It means that a "bridge toll" must be paid for each cycle).

In order to reduce the cost, we adopt a more efficient method, for example:


function innerHTMLLoop2(){
   var content = ' ';
   for(var count = 0;count < 15000 ;count++){
      content +='a';
  } 
  document.getElementById('here').innerHTML +=content;
}

In this way, the same function can be completed only by paying the "bridge crossing fee" once. Running speeds are significantly improved in different browsers, such as IE6, where using innerHTMLLoop2 () is 155 times faster than using innerHTMLLoop (). (So in reality, many large trucks are overloaded to save this cost and earn more once. However, we still do what we can. The program is also one, and the balance exists between everything.)

2. Be within reach

Despite the new browser using the optimized javascript engine, there are some performance issues with object member references. The deeper the unknown object exists in the prototype chain, the slower it is to find it, such as the less common writing: window. location. href. Each time the dot operator is encountered, nesting members causes the Javascipt engine to search for all object members. The deeper the object members are nested, the slower the reading speed will be. Executing location. href is always faster than window. location. href, which is also faster than window. location. href. toString (). If these attributes are not instance attributes of the object, then member resolution also requires searching the prototype chain, which takes more time.

Since similar performance issues are related to object members, they should be avoided whenever possible. More precisely, it should be noted that object members are used only when necessary. For example, it is not necessary to read the same object member multiple times in the same function. Example:


function hasEitherClass(element,className1,className2){
   return element.className == className1 || element.className == className2; 
}

The above code was read twice by element. className. It means that in this function statement, both member lookups are by reading attribute values, so it is necessary to store the values in local variables after finding them for the first time, because the reading speed of local variables is much faster. Example:


function hasEitherClass(element,className1,className2){
   var currentClassName = element.className;
   return currentClassName == className1 || currentClassName == className2; 
}

The above element. className assigns values to currentClassName local variables, avoiding the performance overhead of multiple lookups. (If you need global object members multiple times, assign them where they are most readily available, thus reducing the number of searches and lookups.)

Summarize

Although I still have a lot to talk about, there are too many ways to optimize performance, and there are better ways to add it later. However, optimization is to find a way with people to do the biggest thing with the least strength. To say the vulgar point is "lazy", and we let the program be lazy.

Here are a few tips for optimizing client JS performance:

1. [Top] Regarding the loop of JS, loop is a common process control. JS provides three cycles: for (; ; ), while (), for (in). Of these three loops, for (in) is the least efficient, because it needs to query Hash key, so for (in) loops and for (; ; ), while () cycle performance is basically the same. Of course, the for loop is recommended. If the loop variable increments or decrements, do not assign a value to the loop variable separately, but use nested + + or--operators.

2. If you need to traverse the array, you should cache the array length first, and put the array length into local variables to avoid querying the array length many times.

3. Local variables are accessed faster than global variables, because global variables are actually members of window objects, and local variables are placed in the function stack.

4. Use eval as little as possible. It takes a lot of time to use eval every time. At this time, function templates can be implemented by using closures supported by JS.

5. Try to avoid nested queries of objects. For the statement obj1.obj2.obj3.obj4, you need to do at least 3 query operations. First check whether obj2 is contained in obj1, then whether obj3 is contained in obj2, and then whether obj4 is contained in obj3... This is not a good strategy. You should use local variables as much as possible and save obj4 as a local variable to avoid nested queries.

6. When making operators, try to use operation symbols such as +=, -=, *=,\ =, etc., instead of directly performing assignment operations.

7. [Top] When you need to convert numbers into characters, use the following method: "" + 1. From the performance point of view, when converting numbers into characters, there is the following formula: ("" +) > String() > .toString() > new String (). String () is an internal function, so it is very fast. While. toString () queries the function in the prototype, so it is less fast than 1, new String () needs to recreate 1 string object, which is the slowest.

8. [Top] Math. floor () or Math. round () should be used when converting floating-point numbers to integers. Instead of using parseInt (), this method is used to convert strings into numbers. And Math is an internal object, so Math. floor () doesn't actually have much query method and call time, and it is the fastest.

9. Try to use the JSON format to create objects instead of the var obj = new Object () method. Because the former is a direct copy, while the latter requires calling the constructor, the former has better performance.

10. When you need to use arrays, try to use the syntax of JSON format, that is, define arrays directly using the following syntax: [parrm, param, param...], instead of using the syntax of new Array (parrm, param, param...). Because the syntax in JSON format is interpreted directly by the engine. The latter requires calling the constructor of Array.

11. [Top] Regular expressions are used for loop operations on strings, such as replacement and lookup. Because the cycle speed of JS is slow, and the operation of regular expression is API written by C, the performance is better.

Finally, there is a basic principle. For large JS objects, caching should be considered as much as possible because of the time and space overhead when creating them.


Related articles: