Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Summary of JavaScript performance optimization tips (including examples)


May 06, 2021 JavaScript


Table of contents


JavaScript already has an important place in many languages, and there are many things we can do with JavaScript that can be used in a wide range of applications. I n web applications, a lot of JavaScript code is required, and more and more will be necessary in the future. H owever, because JavaScript is a language for interpreting execution, and its single-threaded mechanism determines that performance issues are a weakness of JavaScript and a problem that developers need to be aware of when writing JavaScript, web 2.0 applications often experience poor performance, mainly due to insufficient JavaScript performance, resulting in overburdened browsers. J avaScript performance optimization is by no means a written skill, so how should JavaScript code be loaded and executed correctly to improve its performance in the browser? Here's a summary of your knowledge of optimization tips.


Whether the current JavaScript code is embedded or in an external chain file, the download and rendering of the page must stop and wait for the script to execute. T he longer javaScript takes to execute, the longer the browser waits for user input. B rowsers are blocked when downloading and executing scripts because the scripts can change the page or JavaScript's namespace, which can affect the content of later pages. A typical example is when using:

document.write()
Example:
<html>
<head>
    <title>Source Example</title>
</head>
<body>
    <p>
    <script type="text/javascript">
        document.write("Today is " + (new Date()).toDateString());
    </script>
    </p>
</body>
</html>
When the browser encounters a tag, the current HTML page has no way of knowing whether JavaScript will add content to the tag, introduce other elements, or even remove the label. T herefore, the browser stops working on the page, executes JavaScript code, and then continues to parse and render the page. T he same thing happens when you load JavaScript using the src property, and the browser must first take the time to download the code in the chain file and then parse and execute it. During this process, page rendering and user interaction are completely blocked.

Do not use with() statements

This is because the with() statement adds additional variables at the beginning of the scope chain. A dditional 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. S o with() essentially gives local variables all the performance drawbacks of global ones, and in turn derails Javascript optimization. So the with() statement negatively affects the performance of both local and global variables, ultimately bankrupting our plan to optimize JavaScript performance.


Object properties and array elements are slower than variables

When it comes to JavaScript data, there are generally four ways to access it: numeric values, variables, object properties, and array elements. When optimizing is considered, the values and variables perform similarly 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 a performance boost by defining a variable. ( This rule works when reading and writing data) Although this rule is correct in most cases, Firefox has done some interesting work in optimizing array indexes to make them perform better than variables. However, given the performance disadvantages of array elements on other browsers, you should try to avoid array lookups unless you are really only developing for the performance of Firefox.


Avoid global lookups

Global objects are stored as local variables in a function to reduce global lookups because access to local variables is faster than access to global variables
function search() {
            //当我要使用当前页面地址和主机域名
            alert(window.location.href + window.location.host);
        }
        //最好的方式是如下这样  先用一个简单变量保存起来
        function search() {
            var location = window.location;
            alert(location.href + location.host);
        }


Avoid with statements

Similar to functions, with statements create their own scopes, thus increasing the length of the scope chain of code executed in them, and because of the extra scope chain lookup, the code executed in the with statement will certainly be slower than the code executed outside, and try not to use the with statement when it is not available.
with (a.b.c.d) {
            property1 = 1;
            property2 = 2;
        }
        //可以替换为:
        var obj = a.b.c.d;
        obj.property1 = 1;
        obj.property2 = 2;

The number is converted into a string

It's best to convert a number into a string with "" and 1, which may seem ugly, but in fact this is the most efficient, performance-effective:
(“” +) > String() > .toString() > new String()

Replace CreativeElement with the template element clone

Many people like to use document.write in JavaScript to generate content for pages. I n fact, this is inefficient, if you need to insert HTML directly, you can find a container element, such as specifying a div or span, and set up their innerHTML to insert their HTML code into the page. Usually we might use strings to write HTML directly to create nodes, but in fact, 1: there is no guarantee of code validity, 2: string operation is inefficient, so it should be done using the document.createElement() method, and if there are ready-made model nodes in the document, It should be the cloneNode() method, because after using the createElement() method, you need to set the properties of elements multiple times, and using cloneNode() reduces the number of times the properties are set -- again, if you need to create many elements, you should prepare a model node first.
 var frag = document.createDocumentFragment();
        for (var i = 0; i < 1000; i++) {
            var el = document.createElement('p');
            el.innerHTML = i;
            frag.appendChild(el);
        }
        document.body.appendChild(frag);
        //替换为:
        var frag = document.createDocumentFragment();
        var pEl = document.getElementsByTagName('p')[0];
        for (var i = 0; i < 1000; i++) {
            var el = pEl.cloneNode(false);
            el.innerHTML = i;
            frag.appendChild(el);
        }
        document.body.appendChild(frag);

Avoid inefficient script locations

The HTML 4 specification states that the label can be placed in the HTML document's slt;head;or in the HTML document, and is allowed to appear more than once. Web developers are generally used to loading JavaScript of the outer chain in the . and then using the hashtag to load the CSS file or other page information of the outer chain.

Examples of inefficient script locations:
<html>
<head>
    <title>Source Example</title>
    <script type="text/javascript" src="script1.js"></script>
    <script type="text/javascript" src="script2.js"></script>
    <script type="text/javascript" src="script3.js"></script>
    <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
    <p>Hello world!</p>
</body>
</html>
However, this routine hides serious performance issues. I n the example in Listing 2, when the browser resolves to the label (line 4), the browser stops parsing the contents thereafter, giving priority to downloading the script file and executing the code in it, which means that neither the styles.css style file nor the label can be loaded, and the page will naturally not render because the label cannot be loaded. S o the page is blank until the JavaScript code is fully executed. The following image describes the download process for scripts and style files during page loading.

Summary of JavaScript performance optimization tips (including examples)

We can find an interesting phenomenon: the first JavaScript file starts downloading, while blocking the download of other files on the page. I n addition, there .js a delay before the download is completed from script1.js to script2.js the download begins. E ach file must wait until the previous file is downloaded and executed before the download begins. During the download of these files one by one, the user sees a blank page.

JavaScript files are allowed to be downloaded in parallel starting with IE 8, Firefox 3.5, Safari 4, and Chrome 2. T hat's good news, because the hashtags don't block other labels when downloading external resources. U nfortunately, the JavaScript download process still blocks downloads of other resources, such as style files and pictures. A lthough the script's download process does not affect each other, the page must still wait for all JavaScript code to download and execute before it can continue. Therefore, although the latest browser improves performance by allowing parallel downloads, the problem has not been fully resolved and script blocking remains an issue.

Because scripts block downloads of other resources on the page, it is recommended that you place all the tags as far as possible at the bottom of the labels to minimize the impact on the entire page download.

Examples of recommended code placement locations:
<head>
    <title>Source Example</title>
    <link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
    <p>Hello world!</p>
    <!-- Example of efficient script positioning -->
    <script type="text/javascript" src="script1.js"></script>
    <script type="text/javascript" src="script2.js"></script>
    <script type="text/javascript" src="script3.js"></script>
</body>
</html>
This code shows the recommended location for placing the hashtag in the HTML document. A lthough the script download blocks another script, most of the content of the page has been downloaded and displayed to the user, so the page download does not appear too slow. This is the first rule for optimizing JavaScript: put the script at the bottom.

Use closures with care

Although you may not yet know "closed packages," you may unanticeticly use this technique frequently. Closures are basically thought of as new in JavaScript, and when we define an instant function, we use closures, such as:
document.getElementById('foo').onclick = function(ev) { };

The problem with closures is that, by definition, there are at least three objects in their scope chain: closure variables, local variables, and global variables. T hese additional objects will cause other performance issues. But Nicholas doesn't want us to waste food, and closures are useful for improving code readability, just don't abuse them (especially in loops).


Tip: If you don't know much about JavaScript closures, please refer to the JavaScript closure section of this site!


The control conditions and control variables are combined during the loop

When it comes to performance, work that needs to be avoided in a loop has always been a hot topic because the loop is repeated many times. So if there is a need for performance optimization, the most obvious performance improvement is likely to be achieved by opening the loop first.

One way to optimize a loop is to combine control conditions and control variables when defining a loop, and here's an example of not merging them:

for ( var x = 0; x < 10; x++ ) {
};
Before we add something to the loop, we find that several operations occur in each iteration. The JavaScript engine requires:
#1:检查 x 是否存在
#2:检查 x 是否小于 0 <span style="color: #888888;">(这里可能有笔误)</span>
#3:使 x 增加 1
However, if you are only an iterative element, you can use the while loop for rotation instead of the above:
var x = 9;
do { } while( x-- );

Use XMLHttpRequest (XHR) objects

This technique first creates an XHR object, then downloads the JavaScript file, and then <script> the page with a dynamic element.

Load JavaScript scripts with XHR objects:
var xhr = new XMLHttpRequest();
xhr.open("get", "script1.js", true);
xhr.onreadystatechange = function(){
    if (xhr.readyState == 4){
        if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
            var script = document.createElement ("script");
            script.type = "text/javascript";
            script.text = xhr.responseText;
            document.body.appendChild(script);
        }
    }
};
xhr.send(null);
This code sends a GET request to the server .js script1 file. T he onreadystatechange event handler checks readyState for 4 and then checks that the HTTP status code is valid (2XX for a valid response and 304 for a cache response). I f a valid response is received, create a new element, setting its text properties to the responseText string received from the server. D oing so actually creates an element with inline code. Once the new element is added to the document, the code is executed and ready to be used.

The main advantage of this approach is that you can download JavaScript code that is not executed immediately. S ince the code returns outside the label (in other words, it is not subject to the label), it is not automatically executed after downloading, which allows you to defer execution until everything is ready. Another advantage is that the same code does not throw exceptions in all modern browsers.

The main limitation of this approach is that JavaScript files must be placed in the same domain as the page and cannot be downloaded from the CDN (CDN refers to the Content Delivery Network), so large web pages typically do not use XHR script injection techniques.


Tip: You can also learn how to create an XHR object in the XHR Creation Objects section of the AJAX Tutorial on this site!

Watch out for NodeList

Minimizing the number of visits to NodeList can greatly improve script performance
 var images = document.getElementsByTagName('img');
        for (var i = 0, len = images.length; i < len; i++) {

        }
When writing JavaScript, be sure to know when to return NodeList objects so that access to them is minimized

1, made a call to getElements ByTagName().
2, obtained the childNodes property of the element
3, obtained the attributes properties of the element
4, access to special collections, such as document.forms, document.images and so on

To understand that when using NodeList objects, proper use can greatly speed up code execution

Avoid comparisons with null

Because JavaScript is a weak type, it doesn't do any automatic type checking, so if you see code compared to null, try replacing it with the following techniques:


1, if the value should be a reference type, use the instanceof operator to check its constructor

2, if the value should be a basic type, the role of typeof to check its type

3. If you want the object to contain a specific method name, use the typeof operator to ensure that the method that specifies the name exists on the object


Respect the ownership of the object

Because JavaScript can modify any object at any time so that you can override the default behavior in unpredictable ways, if you are not responsible for maintaining an object, its object, or its methods, then you should not modify it, specifically by saying:

1. Do not add properties to an instance or prototype
2. Do not add methods for instances or prototypes
3. Don't redefine methods that already exist
4. Don't repeatedly define the methods that other team members have already implemented, never modify objects that aren't owned by you, you can create new features for objects by:
1. Create a new object that contains the required functionality and use it to interact with the related object
2, create a custom type, inherit the type that needs to be modified, and then add additional functionality to the custom type

Loop reference

If the circular reference contains either a DOM object or an ActiveX object, a memory leak occurs. The consequence of a memory leak is that this memory is not released by the browser, even if the page is refreshed, before the browser is closed.

Simple circular reference:
 var el = document.getElementById('MyElement');
        var func = function () {
            //…
        }
        el.func = func;
        func.element = el;
This is not usually the case. Typically, circular references occur when a closure is added to a dom element as an expendo.
  function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
        }
        init();

When init is executing, the current context is called context. A t this point, context refers to el, el refers to fusion, function refers to context. This is when a circular reference is formed.

There are two ways to resolve circular references:


1, empty dom object
 function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
        }
        init();
        //可以替换为:
        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
            el = null;
        }
        init();

Empty el, context does not contain a reference to the dom object, interrupting the looping application.


If we need to return the dom object, we can do so in the following way:

 function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
            return el;
        }
        init();
        //可以替换为:
        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
            try {
                return el;
            } finally {
                el = null;
            }
        }
        init();

2, construct a new context
 function init() {
            var el = document.getElementById('MyElement');
            el.onclick = function () {
                //……
            }
        }
        init();
        //可以替换为:
        function elClickHandler() {
            //……
        }
        function init() {
            var el = document.getElementById('MyElement');
            el.onclick = elClickHandler;
        }
        init();

Draw the function into the new context so that the function's context does not contain a reference to el, thus interrupting the circular reference.

Dom objects created with javascript must be appended to the page

Under IE, the script creates the dom object, if there is no append to the page, refresh the page, this part of the memory will not be reclaimed!

  function create() {
            var gc = document.getElementById('GC');
            for (var i = 0; i < 5000; i++) {
                var el = document.createElement('div');
                el.innerHTML = "test";
                //下面这句可以注释掉,看看浏览器在任务管理器中,点击按钮然后刷新后的内存变化
                gc.appendChild(el);
            }
        }


String connection

If you want to connect more than one string, you should use less, such as

s+=a;

s+=b;

s+=c;

Should be written as s

And if you're collecting strings, such as multiple times working on the same string, it's a good idea to use a cache, use a JavaScript array to collect them, and finally connect them using the jon method

var buf = [];
        for (var i = 0; i < 100; i++) {
            buf.push(i.toString());
        }
        var all = buf.join("");

JavaScript programming live: How JavaScript strings are connected

Various types of conversions

var myVar = "3.14159",
        str = "" + myVar, //  to string  
        i_int = ~ ~myVar,  //  to integer  
        f_float = 1 * myVar,  //  to float  
        b_bool = !!myVar,  /*  to boolean - any string with length 
                                and any number except 0 are true */
        array = [myVar];  //  to array
If the toString() method is defined for type conversion, it is recommended to explicitly call to toString(), because internal operations will try to convert the object's toString() method after all possibilities have been tried, so it would be more efficient to call this method directly

Multiple type declarations

In JavaScript, all variables can be declared using a single var statement, which is a combined statement to reduce the execution time of the entire script, just like the code above, the above code format is quite standardized, let people see clearly.

Insert the iterator

e.g. var name-values; i ++; The first two statements can be written as var name-values.

Use a direct amount

var aTest = new Array(); //替换为
        var aTest = [];
        var aTest = new Object; //替换为
        var aTest = {};
        var reg = new RegExp(); //替换为
        var reg = /../;
        //如果要创建具有一些特性的一般对象,也可以使用字面量,如下:
        var oFruit = new O;
        oFruit.color = "red";
        oFruit.name = "apple";
        //前面的代码可用对象字面量来改写成这样:
        var oFruit = { color: "red", name: "apple" };

Avoid double interpretation

If you want to improve your code performance, try to avoid strings that need to be interpreted by JavaScript, that is
1, as little as possible to use the eval function
Using eval is equivalent to calling the interpretation engine again at runtime to run the content, which takes a lot of time, and the security issues that come with using eval cannot be ignored.

2. Do not use the Fusion constructor
Do not pass string parameters to setTimeout or setInterval
 var num = 0;
        setTimeout('num++', 10);
        //可以替换为:
        var num = 0;
        function addNum() {
            num++;
        }
        setTimeout(addNum, 10);

Shorten the negative detection

 if (oTest != '#ff0000') {
            //do something
        }
        if (oTest != null) {
            //do something
        }
        if (oTest != false) {
            //do something
        }
        //虽然这些都正确,但用逻辑非操作符来操作也有同样的效果:
        if (!oTest) {
            //do something
        }

Release the javascript object

In rich applications, memory consumption increases as the number of instantiated objects increases. Therefore, references to objects should be released in a timely manner so that the GC can reclaim these memory controls.

Object: obj s null

Object properties: delete obj.myproperty

Array item: Use the array's splice method to release the items that are not used in the array


Performance considerations

1, try to use the native method

2, switch statement is relatively fast

Organize case statements in the most likely to least likely order

3, bit operation is faster

Bit operations are faster than any Boolean or arithmetic operations when numeric operations are performed

4, clever use of || and the operator of the and the operator of the

 function eventHandler(e) {
            if (!e) e = window.event;
        }
        //可以替换为:
        function eventHandler(e) {
            e = e || window.event;
        }
  if (myobj) {
            doSomething(myobj);
        }
        //可以替换为:
        myobj && doSomething(myobj);

Avoid errors where you should be aware of them

1, the end of each statement must be added a sign

In an if statement, even if the conditional expression has only one statement, it is enclosed with a statement, lest a subsequent logical error be caused if the statement is added


2. Be careful when using the plus sign

Unlike other programming languages, in JavaScript, in addition to representing the addition of numeric values and the connection of strings, a string can be used as a meta-operator to convert strings to numbers. Therefore, if used improperly, it may be confused with the self-adder ' and cause a computational error

 var valueA = 20;
        var valueB = "10";
        alert(valueA + valueB);     //ouput: 2010 
        alert(valueA + (+valueB));  //output: 30 
        alert(valueA + +valueB);    //output:30 
        alert(valueA ++ valueB);     //Compile error


3, the use of return statements need to pay attention to

A return statement with a return value should not enclose the return value with () parentheses, and if an expression is returned, the expression should be on the same line as the return keyword to avoid compression when the compression tool automatically adds a semically sign, resulting in a return that is inconsistent with the developer

function F1() {
            var valueA = 1;
            var valueB = 2;
            return valueA + valueB;
        }
        function F2() {
            var valueA = 1;
            var valueB = 2;
            return
            valueA + valueB;
        }
        alert(F1());  //output: 3 
        alert(F2());  //ouput: undefined

The difference between a s and a s

Avoid assigning values in the conditional parts of the if and while statements, such as if (a s b), which should be written as if (a sb), but in the case of equality of comparison, it is best to use the full run character, i.e. the operator will be better than the s and! The type cast is performed by the operator
var valueA = "1";
        var valueB = 1;
        if (valueA == valueB) {
            alert("Equal");
        }
        else {
            alert("Not equal");
        }
        //output: "Equal"
        if (valueA === valueB) {
            alert("Equal");
        }
        else {
            alert("Not equal");
        }
        //output: "Not equal"


Do not use raw syntax

Don't use raw syntax, write confusing code, although the computer can correctly identify and run, but obscure code is not convenient for later maintenance

The function returns a uniform type

Although JavaScript is a weak type, for functions, the previous return of integer data, followed by the return of Boolean values in compilation and operation can pass normally, but in order to be easy to understand for specification and later maintenance, you should ensure that the function should return a uniform data type

Always check the data type

Check all the data your method enters, on the one hand for security and on the other for availability. U sers enter incorrect data anytime, anywhere. I t's not because they're stupid, it's because they're busy and think differently from you. Use the typeof method to detect whether the input you accept is legitimate

When to use single quotes and when to use double quotes

Although in JavaScript, both double quotes and single quotes can represent strings, to avoid confusion, we recommend using double quotes in HTML and single quotes in JavaScript, but in order to be compatible with individual browsers, and in order to resolve error-free, it is best to use double quotes when defining JSON objects

Deployment

1, run javaScript validator with JSLint to make sure there are no syntax errors or code without potential questions
2, before deployment is recommended to use compression tools to compress JS files
3, file coding unified with UTC-8
4, JavaScript program should try to put in the .js file, when need to be called in HTML in the form of the "filename.js " . I f JavaScript code is not specific to the HTML file, you should try to avoid writing JavaScript code directly in the HTML file. B ecause this greatly increases the size of the HTML file, it is not helpful for code compression and cache usage. I n addition, the label should be placed as far as possible at.js the back of the file, preferably in front of the label. This reduces the load time that other components in the page are affected by loading JavaScript code.

Never ignore code optimization, refactoring is a work that requires continuous work from project start to finish, and only continuous optimization of code can make code perform more efficiently