Home  >  Article  >  Web Front-end  >  In-depth analysis of JavaScript scope and scope chain_javascript skills

In-depth analysis of JavaScript scope and scope chain_javascript skills

WBOY
WBOYOriginal
2016-05-16 17:10:211110browse

Scope is one of the most important concepts in JavaScript. If you want to learn JavaScript well, you need to understand the working principles of JavaScript scope and scope chain. Today's article provides a brief introduction to JavaScript scope and scope chain, hoping to help everyone learn JavaScript better.

JavaScript Scope

Any programming language has the concept of scope. Simply put, scope is the accessible range of variables and functions. That is, scope controls the visibility and life cycle of variables and functions. In JavaScript, there are two types of variable scope: global scope and local scope.

1. Global Scope

Objects that can be accessed anywhere in the code have global scope. Generally speaking, there are several situations where global scope is available:

(1) The outermost function and variables defined outside the outermost function have global scope, for example:

Copy code The code is as follows:

var authorName="Mountainside Brook";
function doSomething(){
var blogName="";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(authorName); //Mountainside Stream
alert(blogName); //Script error
doSomething(); //
innerSay() //Script error

(2) All variables that are not defined and directly assigned a value are automatically declared to have global scope, for example:
Copy code The code is as follows:

function doSomething(){
var authorName="Shanbian Xiao Stream";
blogName="";
alert(authorName);
}
alert(blogName); //
alert(authorName); //Script error

The variable blogName has global scope, but authorName cannot be accessed outside the function.

(3) All window object properties have global scope

Generally, the built-in properties of the window object have global scope, such as window.name, window.location, window.top, etc.

2. Local Scope

Contrary to the global scope, the local scope is generally only accessible within a fixed code fragment, the most common one is within a function, so in some places you will see people refer to this scope as a function scope. For example, blogName and function innerSay in the following code only have local scope.

Copy code The code is as follows:

function doSomething(){
var blogName=" ";
function innerSay(){
alert(blogName);
}
innerSay();
}
alert(blogName); //Script error
innerSay( ); //Script error

Scope Chain

In JavaScript, functions are also objects. In fact, everything in JavaScript is an object. Function objects, like other objects, have properties that can be accessed through code and a set of internal properties that are only accessible to the JavaScript engine. One of the internal properties is [[Scope]], defined by the ECMA-262 standard third edition. This internal property contains the collection of objects in the scope in which the function is created. This collection is called the scope chain of the function, which determines Which data can be accessed by the function.

When a function is created, its scope chain is populated with data objects accessible in the scope in which the function was created. For example, define the following function:

Copy the code The code is as follows:

function add(num1, num2) {
var sum = num1 num2;
return sum;
}

When the function add is created, a global object will be filled in its scope chain. The global object contains all global variables, as shown in the following figure (note: the picture only illustrates a part of all variables):


The scope of function add will be used during execution. For example, execute the following code:

Copy the code The code is as follows:

var total = add(5, 10);

When this function is executed, an internal object called "execution context" is created. The runtime context defines the environment when the function is executed. Each runtime context has its own scope chain for identifier resolution. When a runtime context is created, its scope chain is initialized to the object contained in [[Scope]] of the currently running function.

The values ​​are copied into the runtime context's scope chain in the order they appear in the function. Together they form a new object called an "activation object". This object contains all the local variables, named parameters, parameter collections and this of the function. Then this object will be pushed to the front end of the scope chain. When the runtime context is destroyed, the active object is also destroyed. The new scope chain is as shown below:

During the execution of the function, if a variable is not encountered, it will go through an identifier parsing process to determine where to obtain and store the data. This process starts from the head of the scope chain, that is, from the active object, and looks for an identifier with the same name. If it is found, use the variable corresponding to this identifier. If it is not found, continue to search for the next object in the scope chain. If If no objects are found after searching, the identifier is considered undefined. During function execution, each identifier undergoes such a search process.

Scope chaining and code optimization

It can be seen from the structure of the scope chain that the deeper the identifier is located in the scope chain of the runtime context, the slower the reading and writing speed will be. As shown in the figure above, because global variables always exist at the end of the runtime context scope chain, finding global variables is the slowest during identifier resolution. Therefore, when writing code, you should use global variables as little as possible and use local variables as much as possible. A good rule of thumb is: if a cross-scope object is referenced more than once, store it in a local variable before using it. For example, the following code:

Copy code The code is as follows:

function changeColor(){

document.getElementById("btnChange").onclick=function(){

document.getElementById("targetCanvas").style.backgroundColor="red";

};

}


This function references the global variable document twice. To find the variable, you must traverse the entire scope chain until it is finally found in the global object. This code can be rewritten as follows:
Copy code The code is as follows:

function changeColor() {

var doc=document;

doc.getElementById("btnChange").onclick=function(){

doc.getElementById("targetCanvas").style.backgroundColor="red";

};

}


This code is relatively simple and will not show a huge performance improvement after rewriting. However, if there are a large number of global variables in the program that are accessed repeatedly, then the rewritten Code performance will be significantly improved.

Change scope chain

The corresponding runtime context is unique each time a function is executed, so calling the same function multiple times will result in the creation of multiple runtime contexts. When the function completes execution, the execution context will be destroyed. Each runtime context is associated with a scope chain. Normally, while the runtime context is running, its scope chain will only be affected by with statements and catch statements.

The with statement is a shortcut way to use objects to avoid writing repeated code. For example:

Copy code The code is as follows:

function initUI(){

with(document){

var bd=body,

links=getElementsByTagName("a"),

i=0,

len=links.length;

while(i < len){

update(links[i ]);

}

getElementById("btnInit").onclick=function(){

doSomething();

};

}

}


The width statement is used here to avoid writing the document multiple times, which seems more efficient, but actually causes performance problems.

When the code runs to the with statement, the scope chain of the runtime context is temporarily changed. A new mutable object is created that contains all the properties of the object specified by the parameter. This object will be pushed into the head of the scope chain, which means that all local variables of the function are now in the second scope chain object, and therefore more expensive to access. As shown below:


Therefore, you should avoid using the with statement in your program. In this example, simply storing the document in a local variable can improve performance.

Another thing that changes the scope chain is the catch statement in the try-catch statement. When an error occurs in the try code block, the execution process jumps to the catch statement, and then the exception object is pushed into a mutable object and placed at the head of the scope. Inside the catch block, all local variables of the function will be placed in the second scope chain object. Sample code:

Copy code The code is as follows:

try{

doSomething();

}catch(ex){

alert(ex.message); //The scope chain changes here

}


Please note that once the catch statement is executed, the scope chain will return to its previous state. The try-catch statement is very useful in code debugging and exception handling, so it is not recommended to avoid it completely. You can reduce the performance impact of catch statements by optimizing your code. A good pattern is to delegate error handling to a function, for example:
Copy code The code is as follows:

try{

doSomething();

}catch(ex){

handleError(ex); //Delegate to the processor method

}


In the optimized code, the handleError method is the only code executed in the catch clause. This function receives an exception object as a parameter, so that you can handle errors more flexibly and uniformly. Since only one statement is executed and no local variables are accessed, temporary changes in the scope chain will not affect code performance.
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn