JavaScript has well-designed rules for storing variables and making it easy to find them. This set of regulations is called scope. So you can define the scope as follows:

Scope is a set of rules on how the management engine can look up variables based on identifier names (identifiers are variable or function names) in the current scope and in nested subscopes

Scopes are divided into static scopes and dynamic scopes. Static scope refers to lexical scope. The scope of a function is determined at the time the function is defined.

Lexical scope

The lexical scope depends on where you put the variable and block scope when you write code, so let’s take a look at this example, right

Function foo(a) {var b = a * 2 function bar(c) {console.log(a, b, c) // 2,4,12} bar(b * 3)} foo(2)Copy the code

JavaScript uses static scoping. Let’s examine the execution:

  • Contains the entire global scope, which has one identifier: foo
  • Contains the scope created by Foo, with three identifiers: a, bar, and b
  • Contains the scope created by bar, with one identifier: c

When the above the console. The log (…). When executed, the code looks for references to a, b, and C, starting with the inner scope. If it cannot find a, it goes up one level to nested foo(…). So it prints 2,4,12

Scope look-ups always start at the inner scope of the run and work outward until they stop at the first identifier. The whole process is the scope chain. 2. No matter where or how a function is called, the lexical scope is determined only by the position at which the function is declared.

Function scope: All variables belonging to this function can be used in the scope of the whole function (nested scopes can also be used). The scope is simply understood as hierarchical, with the inner scope having access to the variables of the outer scope and vice versa.

Functions are scoped at creation time. The first thing you need to know when doing this type of problem is that you want to value the function in the scope where it was created, not where it was called — that’s static scope.

var a = 10
function fn() {
  var b = 20
  function bar() {
    console.log(a + b) //30
  }
  return bar
}
var x = fn(),
  b = 200
x() // bar()
Copy the code

Fn () returns the function bar, which is assigned to x. By executing x(), the bar function code is executed. When taking the value of b, fetch it directly from fn’s scope. The value of a is 30, and the value of a is 30. The value of a is 30, and the value of a is 30

Execution context

JavaScript actually executes a piece of code in two stages, one is compilation and the other is execution.

  • 1. Compilation stage: this stage is done by the compiler to translate the code into executable code. This stage is scoped
  • 2. Execution phase: This phase is done by the JS engine, which mainly executes executable code. The execution context is created (the object is created).

Compilation phase

  • Lexical analysis
  • Parsing (AST Abstract Syntax tree)
  • Code generation scope determined

Execution phase

  • Create execution context
  • Execute function code
  • The garbage collection

The scope is defined when a function is defined, not when the execution context of a function call is created before the function is executed

The execution context is determined at run time and can change at any time; The scope is defined at definition and does not change.

Functions and variables are promoted

We are all familiar with the concept of scope above, but scope and where variable declarations occur are very subtle. I also often hear that var boosts variables. ES6’s let, const block-level scope solves this problem.

Let’s start with an example

A = 2 var a console.log(a) // Output 2Copy the code

The function actually executes in two phases, as we saw in the last section, when Var a = 2; JavaScript sees this as two declarations: var a; And a is equal to 2. The first declaration is made at compile time, and the second assignment declaration is left in place for execution. So it prints 2

Console. log(a) // undefined var a = 2 // This is the same as the actual process var a; console.log(a) a = 2Copy the code

In fact, variable assignment can be divided into three steps: create a variable, initialize a variable (undefined), and actually copy. As you can see from the above example, var was created and initialized to be enhanced, but assignment was not, so the output was undefoned.

A few points to note

  • 1. Functions and variables are promoted
  • Var foo = function(){// function foo = function(){// function foo = function();
  • The function is promoted before the variable

Let, const, and var

To cover all three, let’s look at a typical interview question

for (var i = 0; i < 10; i++) { setTimeout(function () { console.log(i); }, 0); } for (let i = 0; i < 10; i++) { setTimeout(function() { console.log(i); // Output 0 1 2 3 4 5 6 7 8 9 }, 0); }Copy the code

I is declared in the global scope (outside the for body), but when used in the local scope of the for body, the variable is fixed, not promoted, and not influenced by the outside world, so it outputs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Var causes the variable to be promoted. When console.log is executed, the synchronization code for loop is completed and the variable is 10, so print 10 10s. This also involves JavaScript’s event loop mechanism, which we’ll cover later with promises.

Const is a variable that cannot be changed. It is not the value of the variable that is guaranteed to remain unchanged, but the memory address to which it refers. For compound types, the memory address to which a variable points holds only a pointer, and const guarantees only that the pointer is fixed.