Recently, I am rereading "Javascript Advanced Programming 3" and feel that I should write some blogs to record some of the knowledge I learned, otherwise I will forget it. What I want to summarize today is the js execution environment and scope.
First, let’s talk about the execution environment
1. Execution environment
The concept in the book, the execution environment defines other data that variables or functions have access to, and determines their respective behaviors. Each execution environment has a variable object associated with it. All variables and functions defined in the environment are stored in this object. Although we cannot access this object when writing code, the parser will use it in the background when processing data.
The execution environment is a concept, a mechanism that defines whether a variable or function has permission to access other data
In javascript, executable JavaScript code is divided into three types:
1. Global Code, that is, global code that is not in any function, such as: a js file, js code embedded in HTML pages, etc.
2. Eval Code, that is, JS code that is dynamically executed using the eval() function.
3. Function Code, that is, the function body JS code in user-defined functions.
Skip Eval Code and only talk about the global execution environment and the function execution environment.
1. Global environment:
The global environment is the most peripheral execution environment. The global execution environment is considered a window object. Therefore, all global variables and functions are created as properties and methods of window objects. When the code is loaded into the browser, the global execution environment is created (the global execution environment is destroyed only when we close the web page or the browser). For example, in a page, create a global execution environment when JS code is loaded for the first time.
This is also why closures have a memory leak disadvantage. Because external functions in closures are treated as global environment. So it will not be destroyed and will be kept in memory.
2. Function execution environment
Each function has its own execution environment. When execution enters a function, the execution environment of the function will be pushed to the top of an execution environment stack and obtain execution rights. When this function is executed, its execution environment is deleted from the top of the stack and the execution right is returned to the previous execution environment. This is the execution flow in the ECMAScript program.
It can also be interpreted in this way: when a JavaScript function is called, the function will enter the execution environment corresponding to the function. If another function is called, a new execution environment is created, and the execution process is in that environment during the function call. When the called function returns, the execution process returns to the original execution environment. Therefore, running JavaScript code forms an execution environment stack.
When a function is called, the local environment of the function is created (after the code in the function is executed, the environment is destroyed, and all variables and function definitions stored in it are also destroyed).
2-1 Definition period
When a function is defined, a [[scope]] attribute will be created. This object corresponds to a list of objects. The objects in the list can only be accessed internally by JavaScript and cannot be accessed through syntax.
(Scope means scope.)
We define a global function A, and then the A function creates an A's [[scope]] attribute. At this time, [[scope]] only contains the global object [Global Object].
If we define a function B inside A, then function B will also create a [[scope]] attribute. B's [[scope]] attribute contains two objects, one is the active object A's active object Activation Object and the other is the global object. A's active object is in front and the global object is in the back.
In short, the order of the object list in the [Scope] property of a function is the Activation Object object of the previous layer of function, and then the upper layer, all the way to the outermost global object.
Here is the sample code: A has only one scope, B has two scopes
// External function function A(){ var somevar; // Inner function function B(){ var somevar; }}2-2 execution period
When a function is executed, it enters the execution environment of the function. First, it creates its own active object [Activation Object] (this object contains the definition of this, arguments, local variables (including named parameters) and a scope chain of a variable object. Then, copy the scope of the execution environment into [[scope chain]] in order, and finally push the active object to the top of [[scope chain]]. In this way, [[scope chain]] is an ordered stack, which ensures orderly access to all variables and objects that have permission to access to the execution environment.
// The first step is to create the global execution environment. Global execution context and global activity objects. // Define the global [[scope]], which only contains Window objects// Scan the global definition variables and function objects: color【undefined】, changecolor【FD creates changecolor[[scope]], which only contains global activity objects], which are added to the window, so the global variables and global function objects are defined as properties of the window. // The program has been defined so changecolor() can be executed anywhere in this execution environment. The color has also been defined, but its value is undefined// The second step is color assigning "blue"var color = "blue";// It does not require assignment, it refers to its own function changecolor() { // The fourth step enters the execution environment of changecolor// Copy the changecolor [[scope]] to the scope chain // Create active objects, scan to define variables and define functions, anothercolor【undefined】 and swapcolors【FD creates the swapcolors[[scope]] and add the active objects and global active objects】 to the active objects, and also add arguments and this // The active objects push into scope chain top // The program has been defined so swapcolors() can be executed anywhere in this execution environment. Anothercolor has been defined, but its value is undefined // The fifth othercolor assignment "red" var anothercolor = "red"; // It does not require assignment, it refers to its own function swapcolors() { // Step 7 Enter the execution environment of swapcolors and create its active object // Copy swapcolors' [[scope]] to scope chain // Scan to define variables and define function objects, add variables tempcolor【undefined】, arguments and this // Push the active object into scope chain top // Step 8: The tempcolor assignment value of anothercolor, anothercolor and color will be found along the scope chain, and continue to execute var tempcolor = anothercolor; anothercolor = color; color = tempcolor; } // Step 6: Execute swapcolors and enter its execution environment swapcolors();}// Step 3: Execute changecolor and enter its execution environment changecolor();2-3 Access identifier:
When an identifier is encountered during the execution of js code, it will search in the scope chain of the execution context (Execution Context) based on the name of the identifier. Starting from the first object of the scope chain (the function's Activation Object object), if it is not found, search for the next object in the scope chain, and repeat until the identifier definition is found. If the last object in the scope is not found after searching for the search, that is, the global object (Global Object), an error will be thrown, prompting undefined.
2. Scope/Scope Chain (scope/scope chain)
When the code is executed in an environment, a scope chain is created. The purpose of the scope chain is to ensure orderly access to all variables and functions that have permission to access to the execution environment. The entire scope chain is a linked list constructed by variable objects at different execution locations according to rules. The front end of the scope chain is always the variable object in the environment where the code currently being executed is located.
If this environment is a function, its activation object is used as a variable object. The active object only contains one variable at the beginning, which is the arguments object inside the function. The next variable object in the scope chain comes from the function's inclusion environment, and the next variable object comes from the next inclusion environment. In this way, it continues to the global execution environment, and the Variable Object of the global execution environment is always the last object in the scope chain.
As shown in the figure:
Examples in the book:
var color="blue"; function changecolor(){ var anothercolor="red"; function swapcolors(){ var tempcolor=anothercolor; anothercolor=color; color=tempcolor; // Todo something } swapcolors();} changecolor(); // tempcolor and anocolor cannot be accessed here; but color can be accessed;alert("Color is now "+color);Through the above analysis, we can know that the internal environment can access all external environments through scope chains, but the external environment cannot access any variables and functions in the internal environment.
These environments are linear and orderly. Each environment can search for scope chains upwards to query variables and function names; however, any environment cannot enter another execution environment by searching for scope chains downwards.
For the swapcolor() function in the above example, its scope chain includes: swapcolor() variable object, changecolor() variable object, and global object. The local environment of swapcolor() begins to search for variables and function names in its own Variable Object. If it cannot be found, search for the changecolor scope chain upwards. . . . . And so on. However, the changecolor() function cannot access variables in swapcolor
Revelation: Try to use local variables to reduce the search time
1. No block-level scope
Unlike C, C++, and JAVA, Javascript has no block-level scope. Look at the following code:
if(true){ var myvar = "Zhang San"; } alert(myvar);// Zhang SanIf there is a block-level scope, myvar cannot be accessed from the outside. Look at the following
for (var i=0;i<10;i++){ console.log(i) } alert(i); // 10For languages with block-level scope, such as java or c# code, i is a variable initialized for, and cannot be accessed outside for. Because i only exists in the for loop weight, after running the for loop, all variables in the for are destroyed. This is not the case in JavaScript. The variable declaration in for will be added to the current execution environment (here is the global execution environment). Therefore, after the for loop is completed, the variable i still exists in the execution environment outside the loop. Therefore, 10 will be output.
2. Declare variables
When a variable is declared using var, this variable will be automatically added to the nearest available environment. For the inside of a function, the closest environment is the local variables of the function. If the variable is not initialized, the variable is automatically added to the global function.
The code is as follows:
var name = "Xiao Ming"; function getName(){ alert( name ); //'undefined' var name = 'Xiao Huang'; alert(name ); //Xiao Huang}getName()Why is the first name undefined? This is because, the javascript parser enters a function execution environment and scans var and function first.
It is equivalent to promoting the var or function [function declaration] declaration to the top of the execution environment.
In other words, when entering our getName function, the identifier search mechanism finds the var, and the name is the local variable name, not the global name, because the name in the function is promoted to the top.
The above code will be parsed as follows:
var name = "Xiao Ming"; function getName(){ var name; alert( name ); //'undefined' var name = 'Xiao Huang'; alert(name ); //Xiao Huang}getName()Extend the scope chain:
Although there are only two types of execution environments - global scope and functional scope, the scope chain can still be extended in some way. Because some statements can add a temporary variable object to the top of the scope chain.
There are two situations where this happens:
1. The catch block of the try-catch statement;
2. with statement;
The above is all about this article. I hope it will be helpful for everyone to learn and understand the JavaScript execution environment and scope.