Scope is one of the most important foundations of every computer language, and certainly one of the most important concepts of JavaScript. To really understand JavaScript in depth, it is essential to understand JavaScript’s scope chain. Now let’s take a closer look at how JavaScript scopes and scope chains work.

What is the scope of JavaScript

In computer programming, a scope is the part of a computer program where the binding of its name to an entity remains valid. Simply put, scope is the accessible scope of variables and functions, that is, scope controls the visibility and life cycle of variables and functions. In JavaScript, there are two types of scope for variables: global scope and local scope. Local scope is also called function scope.

Global scope

Objects that can be accessed anywhere in the code have a global scope. In general, the following situations have a global scope:

(1) Functions or variables defined in the outermost layer of the program
var a = "tsrot"; function hello(){ alert(a); } function sayHello(){ hello(); } alert(a); // Access tsrot hello(); // Access tsrot sayHello(); // You can access the Hello function, and then also the tsROTCopy the code
(2) All variables that are not directly assigned by definition (not recommended)
function hello(){ a = "tsrot"; var b = "hello tsrot"; } alert(a); // Access tsrot Alert (b); // Error cannot be accessedCopy the code
(3) Properties and methods of all Window objects

In general, the built-in properties of a window object have a global scope, such as window.name, window.location, window.top, and so on.

Local scope (function scope)

A local scope is created within a function and is accessible within the function but not outside it.

function hello(){ var a = "tsrot"; alert(a); } hello(); // Access tsrot alert(a); //error not definedCopy the code

What is the scope chain

Before we get to scope chains, we need to know a few concepts:

  • Declarations of variables and functions
  • The life cycle of a function
  • Activetion Object (AO), Variable Object (VO)

Declarations of variables and functions

When a JavaScript engine parses JavaScript code, it first pre-parses variable and function declarations before it executes the rest of the code.

Variable declaration: There is only one way to declare a variable, and that is with the var keyword. Direct assignment is not the way to declare a variable. This simply creates new properties (not variables) on the global object. There are a few differences: (1) Because it is just an assignment, it is not declared ahead

alert(a); // undefined
alert(b); // error "b" is not defined
b = 10;
var a = 20;Copy the code

(2) The direct assignment form is created during execution

alert(a); // undefined, b = 10; alert(b); Var a = 20; alert(a); // 20, code execution phase modificationCopy the code

(3) Variables cannot be deleted. Attributes can be deleted

a = 10; alert(window.a); // 10 alert(delete a); // true alert(window.a); // undefined var b = 20; alert(window.b); // 20 alert(delete b); // false alert(window.b); // Still 20, because variables cannot be deleted.Copy the code

However, there is an exception, which is that variables can be deleted in the context of “eval” :

eval('var a = 10; '); alert(window.a); // 10 alert(delete a); // true alert(window.a); // undefinedCopy the code

Some debug tools can also be removed because they use the eval() method to execute code.

Function name(){} Function name(){

function add(a,b){ return a+b; } the add (5, 4);Copy the code

(2) Create the new Funtion constructor function

var add=new Function("a", "b", "return a+b;" ); Add (4, 5);Copy the code

(3) Create an anonymous function method to assign values to variables

var add = function(a,b){ return a+b; } the add (4, 5);Copy the code

The latter two methods, when accessed before the declaration, return a undefined variable. Of course, accessing them after declaration is a function.

Note: If the variable name and function name are declared the same, the function is declared first.

alert(x); // function var x = 10; alert(x); // 10 x = 20; function x() {}; alert(x); / / 20Copy the code

The life cycle of a function

The life cycle of a function is divided into two phases: creation and execution.

In the function creation stage, the JS parsing engine performs pre-parsing, which will advance the function declaration and put the function into the global scope or the local scope of the function above the current function.

In the function execution stage, the JS engine will declare the local variables and internal functions of the current function in advance, and then execute the business code. When the function exits after execution, the execution context of the function will be released, and the local variables of the function will be cancelled.

What are AO and VO

AO: Activetion Object VO: Variable Object

VO corresponds to the function creation stage. When the JS parsing engine performs pre-parsing, all the declarations of variables and functions are collectively called Variable Object. This variable is context-dependent, knows where its data is stored, and knows how to access it. VO is a special execution context-specific object that stores the following declared in the context:

  • Variables (var, variable declaration);
  • FunctionDeclaration (FD);
  • Parameter to a function

Here’s an example:

function add(a,b){ var sum = a + b; function say(){ alert(sum); } return sum; } // sum,say,a,b is the sum of VO, but the value of this object is undefinedCopy the code

AO corresponds to the execution stage of a function. When a function is called and executed, an execution context will be established, which contains all the variables required by the function. The variables together form a new Object called Activetion Object. This object contains:

  • All local variables of a function
  • All named arguments to the function
  • The set of arguments to a function
  • The function this points to

Here’s an example:

unction add(a,b){ var sum = a + b; function say(){ alert(sum); } return sum; } the add (4, 5); // arguments: [4,5], // a: 4, // b: 5, // say:, // sum: undefined //}Copy the code

JavaScript scope chain

Now let’s return to the subject of scope chains.

When code is executed in an environment, a scope chain of variable objects is created to ensure orderly access to variables and functions that the execution environment has access to. The first scoped object is always the variable object (VO) of the environment in which the code is currently executing.

function add(a,b){
	var sum = a + b;
	return sum;
}
Copy the code

Suppose the function is created in the global scope. When function A is created, its scope chain is filled with the global object, which contains all the global variables, and the global variable is VO. The scope chain is:

Global Object Scope (VO) VO = {this: window, add:}Copy the code

In the case of the function execution phase, its Activation Object (AO) is the first object in the scope chain, the second object is the execution context AO of the parent function, and so on.

Add (4, 5);Copy the code

For example, the scope chain after the add call is:

Global Object (VO) Scope (add) -> AO -> VO AO = {this: window, arguments: [4,5], a: 4, b : 5, sum : undefined } VO = { this : window, add : }Copy the code

During the operation of a function, identifier parsing is a process of searching level by level along the scope chain, starting from the first object and working backwards step by step until the identifier with the same name is found. When it is found, it does not continue to traverse, and an error is reported if it cannot be found.

After reading the above content, maybe some people do not understand, I will explain it again, first take an example:

var x = 10;
 
function foo() {
    var y = 20;
 
    function bar() {
        var z = 30;
 
        console.log(x + y + z);
    };
 
    bar()
};
 
foo();Copy the code

The output of the above code is “60”, and the function bar can access “z” directly, and then the upper “x” and “y” through the scope chain. The scope chain is:

At this point, the Scope Chain has three levels, the first level is Bar AO, Global Object (VO) scope -> bar.AO -> foo.AO -> Global Object bar.AO = {z: 30, __parent__ : foo.AO } foo.AO = { y : 20, bar : , __parent__ : } Global Object = { x : 10, foo : , __parent__ : null }Copy the code

To be continued…