


In-depth analysis of JavaScript scope and scope chain_javascript skills
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:
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:
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.
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:
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:
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:
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:
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:
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:
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:
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.

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



typedef struct is used in C language to create structure type aliases to simplify the use of structures. It aliases a new data type to an existing structure by specifying the structure alias. Benefits include enhanced readability, code reuse, and type checking. Note: The structure must be defined before using an alias. The alias must be unique in the program and only valid within the scope in which it is declared.

Variable expected value exceptions in Java can be solved by: initializing variables; using default values; using null values; using checks and assignments; and knowing the scope of local variables.

Advantages of JavaScript closures include maintaining variable scope, enabling modular code, deferred execution, and event handling; disadvantages include memory leaks, increased complexity, performance overhead, and scope chain effects.

The #include preprocessor directive in C++ inserts the contents of an external source file into the current source file, copying its contents to the corresponding location in the current source file. Mainly used to include header files that contain declarations needed in the code, such as #include <iostream> to include standard input/output functions.

Life cycle of C++ smart pointers: Creation: Smart pointers are created when memory is allocated. Ownership transfer: Transfer ownership through a move operation. Release: Memory is released when a smart pointer goes out of scope or is explicitly released. Object destruction: When the pointed object is destroyed, the smart pointer becomes an invalid pointer.

Can. C++ allows nested function definitions and calls. External functions can define built-in functions, and internal functions can be called directly within the scope. Nested functions enhance encapsulation, reusability, and scope control. However, internal functions cannot directly access local variables of external functions, and the return value type must be consistent with the external function declaration. Internal functions cannot be self-recursive.

In Vue, there is a difference in scope when declaring variables between let and var: Scope: var has global scope and let has block-level scope. Block-level scope: var does not create a block-level scope, let creates a block-level scope. Redeclaration: var allows redeclaration of variables in the same scope, let does not.

In JavaScript, the pointing types of this include: 1. Global object; 2. Function call; 3. Constructor call; 4. Event handler; 5. Arrow function (inheriting outer this). Additionally, you can explicitly set what this points to using the bind(), call(), and apply() methods.
