Efficient programming of JavaScript

Source: Internet
Author: User
Tags expression engine

Objective:

JavaScript is definitely one of the most popular programming languages, has a large user base, has a wide range of application prospects. In the front-end development, it is also one of the three carriages, and is the most important link. Optimizing JavaScript programs and improving execution efficiency is essential to provide users with a smoother operation experience and more friendly interactions. So how can we write a high-performance JS program? This article is in the reading "high-performance Web site Construction Advanced Guide" and "high-performance JavaScript" After a summary, I also deepen the impression, hope to help everyone!

first, data access

1. Efficient data storage

where the data is stored in the script affects the execution time of the script. There are generally four ways to store data:

    • Literal value
    • Variable
    • Array elements
    • Object Properties

Storing data in different ways can lead to different performance costs. In most browsers, the cost of reading from the literal and reading from a local variable is minimal and almost negligible. The real difference in reading data from an array or an object, the experiment shows that the storage of arrays and objects is more expensive than the other two by experiments on the storage locations of the above four different data types.

To improve data storage efficiency, we need to store those values that require frequent access into local variables.

function process (data) {     if (data.count>0) {for           (var i=0;i<data.count;i++) {                 ProcessData (data.item [i]);}}}     Storing the Data.count to local variables requires only one read, and the other reads the function process (data) {     var count = data.count) in the local variable;     if (count>0) {for           (var i=0;i<count;i++) {                 processdata (data.item[i]);           }     }}

Also, with the deepening of data structure, it will also have a negative impact on the information access. As Data.item.subitem.count is slower than Data.count.

It is a good idea to use object properties or array elements stored as local variables more than once in a JS program. In particular, it is more important to use local variables when dealing with Htmlcollection objects (such as the values returned by DOM methods such as Getelementbytagname or element.childnodes), because each time you access the Htmlcollection object, you will move Query, which means that every read will be queried again, which is a very expensive behavior.

2. Management scopes

We know that JS has the concept of a scope chain, and when the program executes, the JavaScript engine parses identifiers such as variables and function names through the scope chain of the search context. It is retrieved from the innermost part of the chain, in order from the inside out, until the lookup is completed, and the search is finished once the lookup is completed. It is obvious that if the JS engine can find the identifier directly than the outward lookup is much faster, that is, the deeper the identifier in the scope chain, the more time it takes to find and access, and if the scope chain management is unreasonable, it will negatively affect the execution of the script. For now, some browsers have optimized the JS engine, such as Chrome and SAFARI4, and the performance penalty for accessing cross-scope identifiers is not obvious, and other browsers still have a significant impact. In order for the program to run efficiently on many browsers, we must manage the scope well, here are some specific methods for reference only:

    • 1.1 Using local variables

      Local variables are the fastest and most readable identifiers for JS, and we should use local variables whenever possible. If any non-local variable is used more than once in a function in a program, we'd better store it as a local variable to increase the speed. For example:   

  Createchildfor (elementid) { var  element =  document.getElementById (ElementID), newelement  =document.createelement (" div     "); Element.appendchild (newelement);}  //  function   Createchildfor (elementid) { var  doc=< Span style= "color: #000000;" >document, Element  = Doc.getelementbyid (ElementID), Newelement=doc.createelement ("div" ); Element.appendchild (newelement);}   

The original function is to find two times the document in the global scope, and the rewritten function only needs to find the global scope, and the others can do so by finding the local scope. The rewritten function will undoubtedly increase speed, remember that the global object is always the last object in the scope chain, and try to avoid using too many global variables.

    • 1.2 Growth Scope Chain

When code executes, the corresponding scope chain is often kept static. However, when a catch is encountered in the WITH statement and Try-catch, the scope chain is changed. When encountering a with statement, the object property is displayed as a local variable, making it easy to access, meaning that a new object is added to the top of the scope chain, which inevitably affects the parsing of the local identifier. When the WITH statement finishes executing, the scope chain is restored to its original state. Avoid this situation in programming. The catch statement is executed in the same situation as the WITH statement, but it is only executed when the error is caught, and the performance impact is less than the WITH statement.

The management of the scope chain is an efficient and convenient method, only need a small amount of work can improve performance, in peacetime writing JS to pay attention to this problem.

Second , DOM programming

      page rendering and JS parsing inside the browser is not an engine, DOM provides an API for JS to manipulate HTML and XML. In order to put JS on the DOM changes presented, there is no doubt that the page rendering engine and JS engine to communicate, two independent functions as long as through the interface to connect with each other, will incur consumption. And it is in the browser is implemented in JavaScript, JS itself is less efficient than Java or C (JS is interpreted language, side-compilation side execution; Java or C is a compiled language, one compile, direct execution), so the DOM is a bit slow. Dom operations that can negatively affect the program can be broadly categorized into three categories: accessing and modifying DOM elements, modifying the style of DOM elements leading to redrawing (repaint) and Reflow (Reflow), and interacting with the user through DOM event handling.

    The
    • Redraw and reflow overhead is also very large. In particular, reflow, when DOM changes affect the geometry of an element, the browser recalculates the geometry of the element, and other related elements are affected, and the affected elements are reconstructed to the render tree. After the reflow is complete, the browser redraws the affected elements into the screen, which is redrawing. Each rearrangement is very energy-intensive, and the browser optimizes the rearrangement process by queuing the modifications and executing them in batches. However, the time to get these layout information (offsettop,scrolltop,clienttop, etc.) causes the queue to refresh, that is, immediate execution, not full batch execution. So, when you need to get these layout information, you can place them after the batch reflow. In general, to improve performance, you can modify styles in batches, manipulate the DOM tree offline, cache layout information, and reduce the number of access to layout information.
    • If there are a lot of elements on the page, and many elements are bound with event handlers, it can also add to the burden on the browser. The more event bindings, the more memory is consumed by the browser to track each event handler. You can use event delegation to reduce the amount of event bindings and reduce the pressure on your browser.

As for the improvement, the personal feeling follows the current trend. With the release of DOM0, DOM2, and DOM3, the new API is also growing, although some of these new APIs will bring performance problems, but it has provided us with great convenience. In fact, with the rapid development of hardware level, many problems will no longer be a problem.

third, algorithm and process Control

The number of codes is not a measure of how fast a program runs, the most immediate factor that affects performance is how the code is organized, and how the specific problem is resolved.

1. Cycle

Loops are one of the most common patterns in programming, and a dead loop and a long cycle can affect the execution efficiency of a function. There are four types of loops in JS, for loops, while loops, do-while loops, and for-in loops, where only the for-in loop is slower than the other loop modes. So, unless you need to iterate over an unknown number of objects, avoid using the for-in loop.

After selecting the appropriate loop type, the factors that can be optimized are the number of transactions and iterations for each iteration. We need to analyze what we do each iteration, and find out how we can reduce the effort. With regard to reducing the number of iterations, you can use the "Duff's Device" loop-body expansion technique, which allows multiple iterations to be performed in a single loop.

2. Conditional Statements

    • 2.1 Quick Condition Judgment

Using a switch statement or a string of If-else statements is a classic problem in many programming languages.

If statement: When such statements are large, there is a lot of overhead, because the deeper the execution flow of the statement, the more conditions need to be judged. Using a large number of if condition statements is a bad thing, but you can use the following method to improve overall performance.

    • Sort the conditions in descending order of frequency;
    • Refine the IF statement to split the conditional statement into several branches. This completes the match in the case of a small number of judgments.
    • 2.2switch statements

Switch simplifies the structure of multiple conditional judgments and improves performance. switch is very readable, and it is recommended for many languages, not because of itself, but by the compiler of many languages that optimizes the switch statement so that it can be evaluated faster. In JS, if statements are often faster than a switch statement when only one or two conditions are judged, the switch statement tends to be faster when more than two simpler conditions are used. This is because, in most cases, a switch statement takes less time than an if statement to execute a single condition, and a switch is better when a large number of judgments are made.

    • 2.3 Array Query

When there are a large number of discrete values to be tested, the above two methods are relatively inefficient, we can use the value of the query to the literal way to assign to the array or object, the previous conditional query into an array query or object member query. It has a big advantage: you don't have to write any conditional judgment statements, and even if the candidate values increase, there is little additional performance overhead.

3. Recursion

The potential problem with recursive functions is that the terminating condition is ambiguous or the absence of a termination condition causes the function to run long and the user interface is in suspended animation. Also, recursive functions may encounter a browser's "Call stack size limit".

The recursive number supported by the JS engine is directly related to the size of the JS call stack, and when you use too many recursion or even the maximum stack capacity, the browser will error. With regard to the call stack size limit, only IE is related to system free memory, and other browsers are fixed in number. The most common cause of a stack overflow is an incorrect termination condition, so the first step in a recursive mode error is to validate the termination condition. If there are no errors in the termination condition, then it is possible that the algorithm contains too many levels of recursion and can be used in conjunction with iterations, Memoization, or both. Memoization is a way to avoid duplication of effort, which caches the previous calculation for subsequent calculations and avoids duplication of effort.

Four, the regular expression

A regular expression that is not properly optimized can also be an important factor in performance bottlenecks. In some places where a regular expression is required to handle a string, you can refine the expression in the following ways.

  • Focus on how to make the match fast: The reason for the slow regular expression is usually that the process of matching fails is slow, not the process of matching success;
  • Regular expressions start with simple, required characters: The starting tag of a regular expression should test and exclude obviously mismatched positions as quickly as possible;
  • Use quantifier patterns to make the characters behind them mutually exclusive: when the character is adjacent to the characters or the sub-expression can overlap, the number of paths that the regular expression attempts to disassemble the text increases, in order to avoid this situation, the matching pattern is as specific as possible;
  • Reduce the number of branches, narrow the branch range: The branch may require that all branch options be tested at each location in the string, either by using character sets and option groups to reduce the need for the branch, or by pushing the branch over the regular expression position.
  • Use a non-capturing group: Capture group consumes time and memory to record a reverse reference and keep it up to date. If you do not need a reverse reference, you can use non-capturing groups to avoid these costs, such as with (?: ...). To replace (...).
  • Capture only the text of interest to reduce post-processing: If you need to reference a matching section, you should take all means to capture which fragments, and then use the reverse reference to process.
  • Exposing required characters: helps the regular expression engine make informed decisions when querying the optimization process, and can try to make it easier to determine which characters are required.
  • Use the appropriate quantifier;
  • Assign the regular expressions to the variables and use them again;
  • Split complex regular expressions into simple fragments: avoid handling too many tasks in a regular expression.

v. Quick response User Interface

Most browsers allow a single thread to be used to execute JS and update the user interface, meaning that the user interface cannot be updated when JS is executed, and vice versa. The process of co-executing JS and updating the user interface is often referred to as the "browser UI thread". The work of the UI thread is based on a simple queue system where the task is saved to the queue until the process is idle, and the next task in the idle queue is executed. These tasks either execute JS or perform UI updates, including redrawing and reflow. However, the idle state is ideal because all of the user's actions trigger the UI update immediately. If a user tries to interact with the page during a task run, not only does it not have a timely UI update, it may even be possible that a new UI update task will not be created and joined to the queue. In fact, most browsers will stop adding new tasks to the queue in the UI thread when JS runs, which means that the JS task must end as soon as possible, so as not to adversely affect the user experience.

For the browser itself will limit the JS execution time, this limit is divided into: Call stack size limit, long-running script restrictions. Execution is terminated when the program exceeds these limits. Studies have pointed out that if the interface in the 100MS response to user input, users will consider themselves in the "direct manipulation of objects in the interface", more than 100ms users will feel that they have lost contact with the interface, can not give users timely feedback. Because when the JS runtime can not update the UI, so if JS execution more than 100ms will give users a bad user experience, so try to avoid JS execution more than 100ms.

Sometimes even if a variety of methods, JS execution time is still greater than 100 milliseconds, in order to provide a good user experience, we can use the timer to empty the time fragment to the UI update, the update is completed before continuing to execute the program. In addition to using timers, we can also use the new Web Workers API in HTML5 to make the program not occupy the UI thread resources and give the user a friendly interactive experience.

To write efficient JS code, the above is not all the considerations, there are many other ways to make our program more concise and beautiful. Personal feeling optimization code is not exhaustive, master the original JS, to the native JS deepen understanding, according to the characteristics of JS we usually pay more attention, should be able to write efficient code. There are some knowledge points, can not be listed here, we want to have a detailed understanding, it is best to read the original. The original writing is very good, very praise, worth reading!

Efficient programming of JavaScript

Related Article

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.