The scope chain, closure, prototype inheritance, eval, and other features in Javascript bring about various efficiency problems while providing various magical functions, by mistake, the execution efficiency will be low. Javascript is a very flexible language. We can write various types of code as we like, different Code styles will inevitably lead to different execution efficiency. In the development process, there will be scattered access to many methods to improve code performance. Sort out common and easy-to-avoid problems.
Javascript execution efficiency
In Javascript, the scope chain, closure, prototype inheritance, eval and other features bring about various efficiency problems while providing various magical functions. If you use them accidentally, the execution efficiency will be low.
1. Global Import
We will use some global variables (window, document, custom global variables, etc.) in the coding process. Anyone who knows about the javascript scope chain knows that, to access global variables in a local scope, You need to traverse the entire scope chain layer by layer until the top-level scope, and the access efficiency of local variables will be faster and higher, therefore, when some global objects are frequently used in a local scope, they can be imported to a local scope. For example:
The Code is as follows:
// 1. input the module as a parameter
(Function (window, $ ){
Var xxx = window. xxx;
$ ("# Xxx1"). xxx ();
$ ("# Xxx2"). xxx ();
}) (Window, jQuery );
// 2. Save it to a local variable
Function (){
Var doc = document;
Var global = window. global;
}
2. eval and eval-like problems
We all know that eval can use a string as js Code for execution and processing. It is said that the code executed using eval is more than 100 times slower than the code without eval (I did not test the efficiency, if you are interested, you can test it)
JavaScript code performs operations similar to "pre-compilation" before execution: first, an activity object in the current execution environment is created, and set the variables declared with var to the attributes of the active object. However, the value assigned to these variables is undefined, and the functions defined by the function are also added as the attributes of the active object, and their values are exactly the definitions of functions. However, if you use "eval", the code in "eval" (actually a string) cannot identify its context in advance and cannot be parsed and optimized in advance, you cannot perform the pre-compilation operation. Therefore, its performance will be greatly reduced.
In fact, eval is rarely used now. Here I want to talk about two eval-like scenarios (new Function {}, setTimeout, setInterver)
Settimtos ("alert (1)", 1000 );
SetInterver ("alert (1)", 1000 );
(New Function ("alert (1 )"))();
The execution efficiency of the above several types of code is relatively low. Therefore, it is recommended to pass in the anonymous method directly or reference the method to the setTimeout method.
3. Release variables that are no longer referenced after closure ends.
The Code is as follows:
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;
})()
In the above Code, the return value of variable f is the method res returned by the closure composed of an immediate execution function, which retains all variables (a, B, c, etc.) in the closure) therefore, these two variables will remain in the memory space, especially the reference of dom elements will consume a lot of memory, we only use the value of variable a in res. Therefore, we can release other variables before the closure returns.
The Code is as follows:
Var f = (function (){
Var a = {name: "var3 "};
Var B = ["var1", "var2"];
Var c = document. getElementByTagName ("li ");
// *** Other variables
// *** Some operations
// Release unused variables before the closure returns
B = c = null;
Var res = function (){
Alert (a. name );
}
Return res;
})()
Efficiency of Javascript dom operations
In the web development process, the bottleneck of front-end execution efficiency is usually on dom operations. dom operations are performance-consuming, how can we save performance as much as possible during dom operations?
1. Reduce reflow
What is reflow?
When the attributes of a DOM element change (such as color), the browser notifies render to re-depict the corresponding element. This process is called repaint.
If this change involves the layout of elements (such as width), the browser discards the original attributes, recalculates the changes, and passes the results to the render to re-depict the page elements. This process is called reflow.
How to Reduce reflow
1. delete the element from the document, modify the element, and then put it back to the original position (when a large number of reflow operations are performed on an element and its child elements, the effects of the two methods are obvious)
2. Set the display of the element to "none". After modification, change the display to the original value.
3. When modifying multiple style attributes, define the class instead of modifying the style attributes multiple times (recommended by certain)
4. Use documentFragment when adding a large number of elements to the page
For example
The Code is as follows:
For (var I = 0; I <100: I ++ ){
Var child = docuemnt. createElement ("li ");
Child. innerHtml = "child ";
Document. getElementById ("parent"). appendChild (child );
}
The code above will operate the dom multiple times, with low efficiency. You can create documentFragment in the following form, add all elements to the docuemntFragment, and add them to the page without changing the dom structure, only reflow is performed once.
The Code is as follows:
Var frag = document. createDocumentFragment ();
For (var I = 0; I <100: I ++ ){
Var child = docuemnt. createElement ("li ");
Child. innerHtml = "child ";
Frag. appendChild (child );
}
Document. getElementById ("parent"). appendChild (frag );
2. Temporary dom status information
When the Code requires multiple accesses to the status information of the element, we can save it to the variable without changing the status, so as to avoid memory overhead caused by multiple accesses to the dom, A typical example is:
The Code is as follows:
Var lis = document. getElementByTagName ("li ");
For (var I = 1; I //***
}
The above method will access the dom element in every loop. We can simply optimize the Code as follows:
The Code is as follows:
Var lis = document. getElementByTagName ("li ");
For (var I = 1, j = lis. length; I //***
}
3. Narrow the selector search range
When searching dom elements, try to avoid traversing page elements in a large area, use a precise selector whenever possible, or specify the context to narrow the search scope. jquery is used as an example.
• Use less Fuzzy Matching selectors: for example, $ ("[name * = '_ fix']"), and use compound selectors such as id and gradually narrow down $ ("li. active)
• Specify the context: for example, $ ("# parent. class"), $ (". class", $ el), etc.
4. Use event Delegation
Use Cases: a list with a large number of records, each record needs to be bound with a click event, after clicking the mouse to implement some functions, we usually bind listening events to each record. This will cause a large number of event listeners on the page, which is inefficient.
Basic Principles:We all know that events in the dom specification will bubble up. That is to say, events of any element will bubble up to the top level step by step according to the structure of the dom tree without actively blocking event bubbles. Event.tar get (srcElement in IE) points to the event source, so even if we listen to the event on the parent element, we can find the most primitive element that triggers the event, this is the basic principle of delegation. Not much nonsense. example above
The Code is as follows:
$ ("Ul li"). bind ("click", function (){
Alert ($ (this). attr ("data "));
})
In fact, the above statement binds all the li elements to the click event to listen to the events of Mouse clicking on each element, so that there will be a large number of event listeners on the page.
Based on the principle of the listener event described above, let's rewrite it.
The Code is as follows:
$ ("Ul"). bind ("click", function (e ){
If(e.tar get. nodeName. toLowerCase () = "li "){
Alert(((e.tar get). attr ("data "));
}
})
In this way, we can add only one event listener to capture all the events triggered by li and perform corresponding operations.
Of course, we don't have to make judgments on the event source every time, so we can abstract it to the tool class to complete it. The delegate () method in jquery implements this function.
The syntax is $ (selector). delegate (childSelector, event, data, function), for example:
$ ("P"). delegate ("button", "click", function (){
$ ("P"). slideToggle ();
});
Parameter description (derived from w3school)
| Parameters |
Description |
| ChildSelector |
Required. Specifies one or more child elements of the event handler to be appended. |
| Event |
Required. Specifies one or more events to be appended to an element. Multiple event values are separated by spaces. Must be a valid event. |
| Data |
Optional. Specifies additional data to be passed to the function. |
| Function |
Required. Specifies the function that runs when an event occurs. |
Tips: Another benefit of event delegation is that even events triggered by elements dynamically added after the event is bound can also be monitored, in this way, you do not need to bind events to elements on the page each time they are dynamically added.