JavaScript Best Practices: Performance

Source: Internet
Author: User
Tags bitwise operators

Note Scope

Avoid global lookups

An example:

function UpdateUI () {    var IMGs = document.getelementbytagname ("img");    For (var i=0, len=imgs.length; i<len; i++) {        imgs[i].title = document.title + "image" + i;    }    var msg = document.getElementById ("msg");    msg.innnerhtml = "Update complete.";}

The function may look completely normal, but it contains three references to the global Document object. If you have more than one picture on the page, the document reference in the For loop will be executed several times or even hundreds, and each time the scope chain will be searched. By creating a local variable that points to the Document object, you can improve the performance of the function by restricting the global lookup once:

function UpdateUI () {    var doc = document;    var IMGs = doc.getelementbytagname ("img");    For (var i=0, len=imgs.length; i<len; i++) {        imgs[i].title = doc.title + "image" + i;    }    var msg = Doc.getelementbyid ("msg");    msg.innnerhtml = "Update complete.";}

Here, the Document object is first present in the local doc variable, and then the original document is replaced in the remaining code. Compared to the original version, now the function is only one global lookup, certainly faster.

Choose the Right method

1. Avoid unnecessary property lookups

Getting constant values is a very efficient process

var value = 5;var sum = ten + Value;alert (sum);

The code makes four constant value lookups: The number 5, the variable value, the number 10, and the variable sum.

Accessing array elements in JavaScript is as efficient as simple variable lookup. So the following code is as efficient as the previous example:

var value = [5,10];var sum = value[0] + value[1];alert (sum);

Any property lookup on an object takes longer than accessing a variable or array, because a property that has that name must be searched in the prototype chain. the more property lookups, the longer the execution time.

var values = {first:5, Second:10};var sum = values.first + values.second;alert (sum);

This code uses a two-time property lookup to calculate the value of sum. Performing one or two property lookups does not cause significant performance problems, but doing hundreds or thousands of times will certainly slow down execution.

Note Gets a multiple-property lookup for a single value. For example:

var query = window.location.href.substring (Window.location.href.indexOf ("?"));

In this code, there are 6 properties found: Window.location.href.substring () 3 times, Window.location.href.indexOf () and 3 times. as long as you count the number of points in the code, you can determine the number of lookups. this code, because two times used to Window.location.href, the same search carried out two times, so the efficiency is particularly bad.

Once the object property is used multiple times, it should be stored in a local variable. The previous code can be rewritten as follows:

var url = window.locaiton.href;var query = url.substring (Url.indexof ("?"));

This version of the code has a 4-time property lookup, saving 33% compared to the original version.

In general, as long as you can reduce the complexity of the algorithm, it is necessary to reduce. Use local variables as much as possible to replace the property lookup with a value lookup, a further award, if you can access it with a digitized array location, or you can use a named property (such as a NodeList object), then use a numeric position.

2. Optimize loops

The basic optimization steps for a loop are as follows.

(1) Impairment iterations-most loops use an iterator that starts at 0 and increases to a specific value. In many cases, iterators with constant impairment in the loop are more efficient starting with the maximum value.

(2) Simplify termination conditions-because the termination condition is calculated for each cycle, it must be guaranteed as fast as possible. This means avoiding property lookups or other actions.

(3) Simplify the loop body-the loop is the most executed, so make sure that it is optimized to the maximum, ensuring that some other dense computations can be easily removed from the loop.

(4 test loop after use-the most common for loop and while loop are the front test loops.) This post-test cycle, such as do-while, avoids the calculation of the initial termination condition and therefore runs faster.

Here is a basic for loop:

for (var i=0; i < value.length; i++) {    process (values[i]);}

In this code, the variable i increments from 0 to the total number of elements in the values array. The loop can be changed to the I minus value as follows:

for (var i=value.length-1; I >= 0; i--) {    process (values[i]);}

The termination condition was simplified from value.length to 0.

The loop can also be changed into a post-test loop, as follows:

var i=values.length-1;if (i>-1) {    do{        process (Values[i])    }while (--i>=0)//There is an erratum here, the termination condition of the book is (--i> 0), after testing, (--i>=0) is the correct}

The main optimization here is to combine the termination condition and the decrement operator into a single statement, and the loop part has been optimized completely.

Remember that you must ensure that you have at least one value to process when you use the post-test loop, and that an empty array results in an extra loop and the pre-test loop can be avoided.

3. Expand Loops

When the number of loops is determined, eliminating loops and using multiple function calls tends to be faster. Assuming that the values array contains only 3 elements, call process () directly on each element. This expands the loop to eliminate the extra overhead of establishing loops and processing termination conditions, making the code run faster.

Elimination cycle Process (Values[0]);p rocess (values[1]);p rocess (values[2]);

If the number of iterations in the loop cannot be determined beforehand, consider using a technique called a duff device. The basic concept of a duff device is to expand a loop into a series of statements by calculating whether the number of iterations is a multiple of 8.

Andrew B.king proposes a faster duff device technology that divides the do-while cycle into 2 separate loops. Here is an example:

var iterations = Math.floor (VALUES.LENGTH/8), var leftover = values.length% 8;var i = 0;if (leftover>0) {    do{        p Rocess (values[i++]);    } while (--leftover > 0);} do{    process (values[i++]);    Process (values[i++]);    Process (values[i++]);    Process (values[i++]);    Process (values[i++]);    Process (values[i++]);    Process (values[i++]);    Process (values[i++]);} while (--iterations > 0);

In this implementation, the remainder of the calculation is not processed in the actual loop, but is divided by 8 in an initialization loop. When the extra elements are disposed of, continue with the main loop that calls 8 process () at a time.

Using an expansion loop for big data sets can save a lot of time, but for small datasets, the extra overhead may outweigh the cost. It's going to take more code to do the same task, and if it's not a big data set, it's generally not worth it.

4. Avoid double interpretation

There is a double interpretation penalty when JavaScript code wants to parse Kavascript. This happens when using the eval () function or the function constructor and using settimeout () to pass a string argument.

Some code evaluation-AVOID!! Eval ("alert (' Hello world! ')"); /Create new function--Avoid!! var sayhi = new Function ("Alert (' Hello world! ')"); /Set timeout--Avoid!! SetTimeout ("alert (' Hello world! ')", 500);

In each of these examples, you parse a string that contains JavaScript code. This operation cannot be done during the initial parsing process because the code is contained in a string, meaning that a new parser must be started to parse the new code while the JavaScript code is running. Instantiating a new parser has a negligible overhead, so this code is much slower than direct parsing.

Corrected alert (' Hello world! '); /Create new function--modified var sayhi = function () {    alert (' Hello world! ');};/ /Set a timeout--Modified settimeout (function () {    alert (' Hello world! ');}, 500);

If you want to improve code performance, avoid strings that need to be parsed by JavaScript whenever possible.

5. Additional Considerations for Performance

(1) Faster native method

(2) Switch statement faster

(3) Fast bitwise operators

Minimum number of statements

1. Multiple variable declarations

4 statements-a waste of var count = 5;var color = "Blue"; var values = [1,2,3];var now = new Date ();//a statement var count = 5,    color = "bl UE ",    values = [n/a], now    = new Date ();

2. Inserting Iteration values

When using iteration values, merge the statements as much as possible.

var name = values[i];i++;

The preceding 2 sentences have only one purpose: the first gets the value from the values array and then stores it in name, and the second adds 1 to the variable I. These two sentences can be combined into a single statement by iterating through the values of the first statement.

var name = values[i++];

3. Using Arrays and object literals

Creating and initializing arrays with 4 statements-wasting var values = new Array (); Values[0] = 123;values[1] = 456;values[2] = 789;//Creating and initializing objects with 4 statements-wasting VAR person = new Object ();p erson.name = "Nicholas";p erson.age = 29;person.sayname = function () {    alert (this.name);};

In this code, only one array and one object are created and initialized. Each uses 4 statements: one calls the constructor, and the other 3 allocates the data. In fact, it can be easily converted into a literal form.

Only one statement creates and initializes the array var values = [13,456,789];//Only one statement creates and initializes the object var person = {    Name: "Nicholas",    age:29,    Sayname:function () {        alert (this.name);    }};

The rewritten code contains only two statements, reducing the 75% statement volume, which is more valuable in code libraries that contain thousands of lines of JavaScript.
Whenever possible, try to eliminate unnecessary statements by using the literal representation of arrays and objects.

Optimizing DOM Interaction

1. Minimizing on-site updates

Once you need to access the DOM section that is part of the page that is already displayed, then you are doing a live update. The more field updates are carried out, the longer the events that the code takes to complete execution.

var list = document.getElementById (' myList '),    item,    i;for (var i = 0; i <; i++) {    item = Document.create Element ("Li");    List.appendchild (item);    Item.appendchild (document.createTextNode ("Item" + i));

This code adds 10 items to the list. When adding each item, there are 2 live updates: One adds the LI element and the other adds a text node to it. This adds 10 items, which will complete 20 live updates in a total.

var list = document.getElementById (' myList '),    fragment = Document.createdocumentfragment (),    item,    i;for (var i = 0; i < i++) {    item = document.createelement ("li");    Fragment.appendchild (item);    Item.appendchild (document.createTextNode ("Item" + i)); List.appendchild (fragment);

In this example there is only one live update, which occurs after all projects have been created. The document fragment is used as a temporary placeholder to place the newly created item. When a document fragment is passed to AppendChild (), only the child nodes in the fragment are added to the target, and the fragment itself is not added.

Once you need to update the DOM, consider using a document fragment to build the DOM structure and then add it to the existing document.

2. Using innerHTML

There are two ways to create DOM nodes on a page: Using DOM methods such as createelement () and AppendChild (), and using innerHTML. Both methods are similar in efficiency for small dom changes. However, for large DOM changes, it is much faster to use innerhtml than to create the same DOM structure using standard DOM methods.

When innerHTML is set to a value, the background creates an HTML parser and then uses the internal DOM call to create the DOM structure, not the JavaScript-based DOM invocation. Because the internal method is compiled rather than interpreted, execution is much faster.

var list = document.getElementById ("MyList");    html = "";    I;for (i=0; i <; i++) {    html + = "<li>item" + i + "</li>";} list.innerhtml = html;

The key to using innerHTML is to minimize the number of times it is called (as with other DOM operations).

var list = document.getElementById ("MyList");    I;for (i=0; i <; i++) {    list.innerhtml + = "<li>item" + i + "</li>";  Avoid!!! }

The problem with this code is that each loop calls innerHTML, which is extremely inefficient. Calling innerHTML is actually a live update. Building a good one string and then calling innerHTML at once is much faster than calling innerHTML multiple times.

3. Using the event proxy (according to the concept of chapter 13th, I think this should be more appropriate for "event delegation")

4. Note Htmlcollection

Any time you want to access htmlcollection, whether it's a property or a method, is a query on a document that is expensive to query.

var images = document.getelementsbytagname ("img"),    image,    i,len;for (i=0, len=images.length; i < Len; i++) { C2/>image = Images[i];    Processing

Store the length and the current referenced images[i] in variables so that you can minimize access to them. The Htmlcollection object is returned when the following conditions occur:

    • A call to getElementsByTagName () was made;
    • Gets the childnodes attribute of the element;
    • Gets the attributes attribute of the element;
    • Special collections are accessed, such as Document.forms, Document.images, and so on.

JavaScript Best Practices: Performance

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.