What is the scope

One of the most basic functions of almost any programming language is to store values in variables and retrieve or modify them later. Without this function, we would only be able to perform immediate operations on values, such as

1 + 1 = 2;
console.log('1');
Copy the code

This brings us to one of the most dynamic concepts in programming languages — variables. So, how are these variables stored in the computer? Where is it stored? More importantly, how do we find them? These questions need to be answered by a set of rules that govern how to find variables (that is, determine the variable and access permissions of the currently executing code). This set of rules is called scope.

Common scope

There are usually two working models of scope, lexical scope and dynamic scope. Lexical scope refers to the area of a program’s source code where variables are defined. The scope is left unchanged when the lexical analyzer processes the code, and dynamic scope is specified at the time the code is executed. JavaScript uses lexical scopes, for example:

var value = 1;
function foo() {
    console.log(value);
}
function bar() {
    var value = 2;
  foo();
}
bar(); // ??
Copy the code
  • ifJavaScripT takes lexical scope, then executes tofooFunction, depending on where the variable is written, will find the global definitionvalue 1
  • ifJavaScriptWith dynamic scope, the implementation tofooThe function, depending on where it’s running, will be foundbarThe definition of thevalue 2

Methods that cheat lexical scope in JavaSript, such as eval and with statements (not in this article’s comb line).

The function scope and global scope we are familiar with in JavaScript is a definition of variable access based on lexical scope. In a function scope, variables defined inside a function are accessible only inside the function. In a global scope, variables are accessible throughout the program life cycle. The existence of function scope compensates for the lack of block-level scope in JavaScript prior to ES6. In a programming language like C, each piece of code inside curly braces has its own scope, and variables are not visible outside the block of code in which they are declared, known as block-level scope. In JavaScript, function scope is used instead.

Execution context

So how does lexical scope work? An execution context is the context in which the current program is running. There are three types of execution context: global execution context, function execution context, and eval execution context. All execution contexts consist of two phases, the creation phase and the execution phase.

Create a stage

Each context mentioned above consists of the following components

  • The variable object
  • The scope chain
  • thisThe binding

As described in JavaScript Advanced Programming, each execution environment (execution context) has a variable object associated with it (VO, which stores variables and function declarations defined in the context). The variable object is not readable to the program, and only the compiler has access to the variable object. In order to see all this clearly, variable objects exist in some kind of concrete, programmatically accessible way.

For example, for a global execution context, a global variable object is represented as a window object

console.log(this === window)
Copy the code

In the context of function execution, variable objects are not accessible to programs, hence the concept of active objects. When the function is activated, the variable Object is converted to an Activation Object. This AO is initialized by the special Object Arguments Object, for example

function foo(a) {
  var b = 2;
  function c() {}
}
foo(1);
Copy the code

The result of initialization is the AO

AO = {
    arguments: {
        0: 1,
        length: 1
    },
    a: 1,
    b: undefined,
    c: reference to function c(){},
}
Copy the code

Execution phase

Complete the changes to the values initialized during the creation phase and execute the code

The scope chain

As mentioned above, in addition to creating variable objects, each execution environment creates a chain of scopes that ensures orderly access to the variables and functions that have access to them. The scope chain of each execution context consists of the variable object of the current environment and the scope chain of the parent environment. So how is the scope chain constructed? Explain in detail from the code

function test(num){
    var a = "2";
    return a+num;
}
test(1);
Copy the code
  • JSA global execution context is created at the first step of execution, and since the global context has no parent environment, the global scope chain contains only variable objectstestfunction
global scopeChain = variable object // global scopeChain = [test]
Copy the code
  • When the code executes totest(1), begins the first phase of the function execution context —Create a stageThe function initializes an internal property[[scope]], which points to the global scope chain
test[[scope]] = global scopeChain
Copy the code
  • In the execution phase, the function’s scope chain is built, and the first thing to do is copy[[scope]]The value of the attribute
test.scopeChain = [test.[[scope]]]
Copy the code
  • Push the variable object into the scope chain
test.scopeChain = [test.variableObject, test.[[scope]]];
Copy the code

At this point, the entire scope chain is constructed.

The resources

  • Understand the execution context and execution stack in JavaScript
  • JavaScript deep variable objects