This is the fifth day of my participation in the August More text Challenge. For details, see:August is more challenging

preface

No matter what kind of computer programming language, in the final analysis, their role is the access and processing of data, JavaScrpt is no exception. The ability to read data more quickly before processing it has a positive effect on program performance. This article will record some ways to improve the performance of JavaScrpt programming from the perspective of data access and scope chain.


Practical optimization

The use of local variables

If a non-local variable is used more than once in a function, it is best to store it with a local variable. For example, the code looks like this:

function process() {
  const target = document.getElementById('target');  
  const imgs = document. ɡ etElementByClassName ('img');  
  for(let i = 0; i < imgs.length ; i++)(const img = imgs[i];  
    // Omit the relevant processing process
    / /...
    target.appendChild(img) 
  )
}
Copy the code

In the process() function, we first get a specific element and a list of elements through two different member functions of document, respectively, and then do some operations that omit the related processing process. It is worth noting that a document belongs to an object of global scope, which is at the bottom of the scope chain and is resolved last in the identifier resolution process. Since it is used more than once in this function, consider declaring it as a local variable to improve the order in which it is found in the scope chain.

It is also important to note that the statement imgs.length, which counts the number of all DOM nodes of class named img, is executed more than once. After the queried DOM node list is stored in the IMGS, each time the IMGS attribute is read by attribute name or index, the DOM will repeat the search for the page element, which is slow in itself.

Modern front-end frameworks generally adopt virtual DOM to optimize the processing of DOM. This example is just to show that using local variables can significantly reduce the search time for object index values. The optimized code is written as follows:

function process() {
  const doc = document;
  const target = doc.getElementById('target');  
  constImgs = doc. ɡ etElementByClassName ('img');  
  const len = imgs.length;
  for(let i = 0; i < len ; i++)(const img = imgs[i];  
    // Omit the relevant processing process
    / /...
    target.appendChild(img) 
  )
}
Copy the code

The growth of the scope chain

As mentioned earlier, you can speed up identifier resolution and access by declaring frequently used data deeper in the scope chain hierarchy as local variables. If you can elevate global variables to the same level as local variables, can you also elevate them to a higher level than local variables? The answer is yes, adding a new active variable scope before the current local variable scope increases, but increasing the scope chain can be too much of a good thing. With statement, for example, it can function outer variables, ascend to even higher than the current function local variable scope chain access level, the following code as a result of using the with statement can directly access the param attribute values, although convenient but it reduces the show () function had access to a local variable speed, so should use less as far as possible.

const param = {
  name: 'Liu'.value: 25
}
function show(){
  const cnt = 2
  with(param){
    console.log(`name is ${name}`)}}Copy the code

The catch block is used to handle the caught exception, but the scope of the error message is higher than the block in which the local variable is located. Therefore, it is recommended not to handle too much complex business logic in the catch statement. This slows down data access.

Be aware of the use of closures

The closure feature enables functions to access data outside of local variables, such as the following code:

function mkFunc(){
  const name = 'Liu'
  return function showName(){
    console.log(name)
  }
}
const myFunc = mkFunc()
myFunc()
Copy the code

The showName() function is a closure that is created during the execution of mkFunc() and has access to the name local to mkFunc(), which requires creating a scope chain independent of the mkFunc() function.

This feature of closures prolongs the life of local variables in complex functions, where normal functions are freed up after execution. This means that the use of closures can have a higher memory overhead and potentially leak impact. If the logic inside a closure is more complex, there will be more frequent cross-scope access to mkFunc and name, so be aware of side effects when using closures for performance reasons.