Explore Javascript execution efficiency

  • 2020-03-30 04:16:11
  • OfStack

Javascript is a very flexible language, we can write all kinds of code at will, different styles of code is also bound to lead to differences in execution efficiency, the development process is scattered contact with many methods to improve the performance of the code, sorting out the usual more common and easy to avoid problems

Javascript itself performs efficiently
Javascript features such as scoped chains, closures, prototype inheritance, and eval provide all sorts of magical functionality, but they also pose all sorts of efficiency problems, which can lead to poor performance if used carelessly.

1. Global import
We will use more or less in the process of encoding to some global variables (window, the document, the custom global variables, etc.), understand javascript scope chain knows, in access to global variables, the local scope need to traverse the entire layer scope chain until top scope, and more efficient access to a local variable will be faster, so the high frequency of the local scope when using some global objects can be imported into the local scope, such as:


//1. Pass in the module
as a parameter  (function(window,$){
     var xxx = window.xxx;
     $("#xxx1").xxx();
     $("#xxx2").xxx();
 })(window,jQuery);
 
 //2. Save the local variable
 function(){
     var doc = document;
     var global = window.global;
 }
 

Eval and the eval problem
We all know that eval can treat a string as js code, and it is said that code executed with eval is more than 100 times slower than code executed without eval.

JavaScript code before implementation will be similar to the precompiled operation: first of all, will create a current execution environment of active objects, and those who use the var statement variable is set to the activities of the object's properties, but the variable assignment is undefined, and defines the function to the attributes of the object function is also added as activity, and it is function definition of their values. However, if you use "eval", the code in "eval" (which is really a string) cannot recognize its context in advance, cannot be parsed and optimized in advance, or cannot be precompiled. Therefore, its performance will be greatly reduced

In fact, you don't usually use eval these days. What I want to talk about here is the scenario of two eval classes (new Function{},setTimeout,setInterver).


setTimtout("alert(1)",1000);
setInterver("alert(1)",1000);
(new Function("alert(1)"))();

All of the above types of code are inefficient, so it is recommended to directly pass in an anonymous method, or a method reference, to the setTimeout method

3. When the closure ends, variables that are no longer referenced are released


var f = (function(){
    var a = {name:"var3"};
    var b = ["var1","var2"];
    var c = document.getElementByTagName("li");
    //**** other variables
    //*** some operations
    var res = function(){
        alert(a.name);
    }
    return res;
})()

The return value of a variable in the code above f is composed of an immediate execution function closures in the res returned by the method, the variable retained for all variables in the closure (a, b, c, etc.), so the two variables will always reside in memory space, especially for dom element references to memory consumption will be very big, and we use only to a variable's value in the res, therefore, before the closure back our other variables can be released


var f = (function(){
    var a = {name:"var3"};
    var b = ["var1","var2"];
    var c = document.getElementByTagName("li");
    //**** other variables
    //*** some operations
    //The closure releases the variable
that is no longer in use before returning     b = c = null;
    var res = function(){
        alert(a.name);
        }
    return res;
})()

The efficiency of Js manipulation of the dom
In the process of web development, the bottleneck of front-end execution efficiency is often dom operation, which is a very performance consuming thing. How to save performance as much as possible in the process of dom operation?

1. Reduce reflow
What is reflow?
When the attributes of a DOM element change, such as color, the browser tells render to repaint the corresponding element, a process called repaint.

If the change involves an element layout (such as width), the browser abandons the original attributes, recalculates and passes the result to render to redepict the page element, a process called reflow.

Ways to reduce reflows
First, delete the element from the document, and then put the element back to the original position after modification (only when a large number of reflow operations are carried out on an element and its child elements, can the effect of 1,2 methods be more obvious)
Set the element's display to "none" and then change the display to its original value
When modifying multiple style attributes, define a class class instead of modifying the style attribute multiple times (recommended for certain)
Use a documentFragment when adding a lot of elements to a page
For example,


for(var i=0;i<100:i++){     var child = docuemnt.createElement("li");     child.innerHtml = "child";     document.getElementById("parent").appendChild(child); }

 
When the state information of an element needs to be accessed multiple times in the code, we can temporarily store it in a variable with the state unchanged, so as to avoid the memory overhead caused by multiple dom accesses. A typical example is:

When looking for dom elements, try to avoid large area traversal of page elements, use precision selectors, or specify a context to narrow the search, as in jquery

Use less fuzz matching selectors: for example, $("[name*='_fix']"), and more like id and the narrowing down of the compound selector $("li.active")
Specify context: for example $("# parent.class "),$(".class",$el), etc

4. Use event delegates
Usage scenario: a list with a large number of records, each record needs to bind the click event, after the mouse click to achieve some functions, we usually do is to bind the monitoring event for each record, this practice will lead to a large number of event listeners on the page, which is inefficient.

Rationale: we all know that events bubble in the dom specification, meaning that any element's events bubble up to the top of the dom tree without actively preventing them from bubbling. The event object also provides an event.target (srcElement under IE) to point to the event source, so we can find the original element that triggered the event even if we listen on the parent element. This is the basic principle of delegation. Without further ado, the above example

Let's rewrite the principle of listening for events as described above

Of course, we don't have to judge the source of the event every time, but we can abstract it off to the utility class to do. The delegate() method in jquery does this

Grammar is such a $(selector). The delegate (childSelector, event, data, function), such as:


$("div").delegate("button","click",function(){
  $("p").slideToggle();
});

Parameter description (quoted from w3school)
Parameter   describe
ChildSelector  A necessity. Specifies that one or more child elements of an event handler are to be attached.
Event  A necessity. Specifies one or more events to attach to an element. Multiple event values are separated by Spaces. It has to be a valid event.
Data  Optional. Specifies the additional data passed to the function.
Function  A necessity. Specifies the function to run when an event occurs.
Another benefit of the Tips: event delegates is that you can listen for events that fire on elements that are dynamically added after the event binding, so you don't have to bind events to an element every time it is dynamically added to the page


Related articles: