1. Why optimize JavaScript performance?

Performance is one of the most important aspects of creating a Web page or application, and no one wants the application to crash or the web page to fail to load or the user to wait too long. Most users expect the site to load in less than 2 seconds, and if the loading process takes more than 3 seconds, more than 50% of users will leave the site.

So in order to improve this situation, the application of JavaScript is a top priority, and the performance optimization of it is particularly important.

2.DOM is one of the most expensive performance overhead for JavaScript

First, let’s look at what DOM is:

DOM is a W3C (World Wide Web Consortium) standard.

DOM defines standards for accessing HTML and XML documents:

“The W3C Document Object Model (DOM) is a platform – and language-neutral interface that allows programs and scripts to dynamically access and update the content, structure, and style of documents.”

The W3C DOM standard is divided into three distinct parts:

  • Core DOM – The standard model for any structured document
  • XML DOM – The standard model for XML documents (the XML DOM defines the objects and attributes of all XML elements, as well as the methods to access them.)
  • HTML DOM – The standard model for HTML documents (the HTML DOM defines the objects and attributes of all HTML elements and the methods to access them.)

In short, the DOM is the document object model, and the HTML document page is the foundation of everything, without which the DOM would be impossible. When a page is created and loaded into the browser, DOM emerges, transforming the web document into a document object whose main function is to process the web content. In this document object, all elements present a hierarchy, meaning that all elements except the top-level HTML are contained within another element.

Second, JavaScript uses DOM elements with high performance overhead

It’s easy to access DOM elements with JavaScript, and the code is easier to read, but JS doesn’t access DOM elements as fast as you might think, and the more elements you have, the slower you get.

Here is a small test that uses DOM elements and outputs 10000 items:

<div id="container"></div> <script> for(var count=0; count<10000; Count++){document.getelementbyid ('container').innerhtml +='<span>DOM small test </span>; } </script>Copy the code

After you open the Chrome browser, you will find that the page is constantly loading. It takes a relatively long time to load 10000 pieces of data. If the PC performance is poor, the page will be directly unresponsive.

The question is, why? How to optimize?

Because the data was executed 10,000 times? There is indeed a reason for this. The memory consumption is naturally different between executing once and executing 10,000 times, and the memory consumption of the latter is higher. However, the main reason is not here.

– Loading an HTML page is usually fast, but after 10,000 entries, the page is constantly loading. This is also because JS is a single-threaded language. If it does not complete, then the page will always present the loading state, resulting in two kinds of results. One is the page loading timeout. The other is that The Chrome browser is restricted to using memory.

– Where is the memory consumption? Let’s examine the code, starting with the for loop:

for(var count=0; count<10000; count++)Copy the code

It looks like 10,000 cycles would consume a lot of memory, but it doesn’t. 10,000 cycles are actually done in just 1ms, and CPU time is very fast in an operating system CPU.

The real memory hog is Document, which is the main source of performance overhead:

Document.getelementbyid ('container').innerhtml +='<span>DOM small test </span>;Copy the code

First of all, Chrome allocates a certain maximum amount of memory to each TAP process, which is limited by the operating system. Executing 10000 data seems to make the page on the verge of crashing. Therefore, in this operating environment, there is a very limited amount of memory available for Javascript to reduce memory consumption. Improving the efficiency of opening pages is especially important.

Secondly, the document is the document object, the DOCUMENT page of HTML is the foundation of everything, without it the DOM would be impossible, with it we can manipulate DOM elements through JavaScript. This code looks for elements through document. Normally, one lookup is enough, but here it looks 10,000 times. This is a problem caused by a weakness in the code that people who have no concept of performance optimization often write.

Some might argue that finding elements is cheap, but the overhead is different when DOM is used here. Don’t worry, let’s start with optimizing the code:

<div id="container"></div> <script> let oContainer=document.getElementById('container'); for(var count=0; count<10000; Count++){ocontainer.innerhtml +='<span>DOM small test </span>'; } </script>Copy the code

By redefining an object and using document.getelementById (), you save 9999 lookups of the element.

So why is DOM so expensive?

When you see a page, it opens in two steps, which involves some underlying principles.

1. Download HTML, CSS, which is the first step of the browser in rendering the page.

An HTML DOM tree is formed so that the tree can be queried. Because HTML file code is an open and closed structure, the use of switch tags such as: is used to form such a DOM tree. Because the browser itself is written by C/C++, if DOM is to be displayed and queried on the page, it must form a tree structure. HTML and file directory are very similar, are written using tree such a data structure, so it will be a DOM tree to form the structure and hierarchy of HTML. The body is the root node, and then the node is attached to it, which is a nice way to do it in a tree.

Next is the parsing of the CSS, which is based on the DOM tree, generating the CSS rendering tree CSSOM, because CSS has selectors and properties to form a Render tree, because the tree structure executes quickly, so it can match the HTML DOM tree.

2.JavaScript=>Style=>Layout=>Paint=>Composite=>Reflow? =>Repaint? Render Tree (CSSOM) : Render Tree (CSSOM) : Render Tree (CSSOM) : Render Tree (CSSOM) Repaint: part of the screen that has been redrawn does not affect the overall layout, such as the background color of a CSS that has changed, but the geometry and position of the elements remain the same.

So when we write a page, must put on the back of the body, this is the first optimization code, we don’t need to this page, but we need to see a static page as soon as possible, to display the page, then as long as the HTTP request to the HTML page to us, immediately formed a DOM tree, Check for link, SRC tags to generate the CSS rendering tree CSSOM.

All in all, the actual overhead of manipulating the DOM is causing the browser to reflow and redraw the reflow, which consumes CPU resources, and if this process is repeated 10,000 times, it will consume a lot of memory.

JavaScript is an extremely poor performance guy:

1. The performance of JavaScript is relatively slow compared to Java, because Java is the underlying memory manipulation level language, JavaScript is only 1/5 of its performance speed, so it is not realistic to compete with PHP, Python and other faster scripting languages. However, the application scenario of JavaScript is the only language that can do the front-end at present. Although Go language is also emerging, it still cannot compete with JavaScript for the time being, and JavaScript can do the back-end and mobile terminal through Node.

2.JavaScript is in a sense a third party because of the browser, and DOM trees and CSS rendering trees are paired to render static pages quickly, which is the first priority.

Write a listening event:

document.addEventListener('DOMContentLoaded',()=>{            
console.log('DomContentLoaded');        
},false);       
window.addEventListener('load',()=>{            
console.log('loaded');        
},false)
Copy the code

Let’s look at the output order:

Obviously, DomContentLoaded executes first, loaded executes after. Produce this kind of situation is due to when the “document. The addEventListener (‘ DOMContentLoaded ‘() = > {” execution, DOM and CSS completed, display a static page, earlier output; When “window.addeventListener (‘load’,()=>{” is executed, various resources such as js, img, SRC… , takes a lot of time, so the run output is slow.

JS is the third party, when the DOM tree is combined with the CSS rendering tree, it can also manipulate the DOM, it can also manipulate the style, its mission is to manipulate the dynamic DOM, the implementation of dynamic pages, so document.getelementById (“) will have a huge overhead, The overhead is from the JS(language world) -> HTML + CSS DOM tree world, which is not available in other languages, and the DOM test document.getelementById (” “) traverses the two worlds 10,000 times, which is quite expensive.

So, is there room for tweaking DOM mini-tests?

Yes, and the key is this code:

Ocontainer. innerHTML+='<span>DOM small test </span>'Copy the code

Because the document is expensive to read and the innerHTML is even more expensive to write, the code is optimized accordingly:

let oContainer=document.getElementById('container'); //read let content='' for(var count=0; count<10000; Count++){content+='<span> I'm a small test </span>'; //js java c++ //read} oContainer .innerHTML+=content;Copy the code

We can’t save 10,000 operations, so declare a content event and have 10,000 of them do a memory level string concatenation in that one event, which is the same language level overhead as JAVA and C++, because it’s only done in the JS world, so it’s done very quickly.

We need to understand that the JS world and the HTML + CSS DOM tree world are two different worlds. So when we come across a place where we can manipulate the DOM tree, we need to pause and see if we can optimize it. For example, when we start JS, Try to find elements at the beginning of the search, and then reference it, do not find and reference every time, this will lead to the first, repeated code; Second, the performance is poor.