JavaScript has a feature called Scope. Although the concept of scope is not easy to understand for many new developers, I will try to explain scopes and scope chains in the simplest way I can in this article. I hope you find it useful! Okay, let’s start our text

Common explanation of scope (what is scope)

  1. The name used in a piece of program code is not always valid, and the scope that defines its availability is the scope of the name;
  2. A scope specifies how to find a variable, that is, determine the access to the variable for the currently executing code;
  3. In layman’s terms, a scope is a set of rules that determine where and how to look for a variable.
function func(){
  var a = 100;
  console.log(a); / / 100
}
console.log(a) // a is not defined a variable can be found everywhere
Copy the code

Scope working model in JavaScript

JavaScript’s use is lexical scoping, also known as static scope:

The scope of a function is determined when the function is defined, and the corresponding dynamic scope is:

The scope of a function is determined at the time the function is called;

Global and local variables

According to the way of defining variables can be divided into: local variables and global variables

Local variables: variables defined in a function that can only be accessed from within the function, not outside the function.

function fn(){
   var name = 'Symbol.;
   console.log(name,"Name in the function");
}
console.log(name,"Name outside the function"); 
fn(); Copy the code

Global variables: Objects that can be accessed from anywhere have global scope, variables defined outside the function;

All variables that do not define a direct assignment are automatically declared to have a global scope

var num = 100;
console.log('num1---',num);
function fn(){
  num = 1000;
  console.log('num2---',num);
} console.log('num3---',num); fn(); console.log('num4---',num); // Run the result //num1--- 100 //num3--- 100 //num2--- 1000 //num4--- 1000 Copy the code

Prior to ES6 JavaScript did not have block-level scopes, only global scopes and function scopes. With the advent of ES6, we have ‘block-level scope’, which can be embodied by the addition of the let and const commands.

2. Understand scope

Understand lexical scope

var value = 1;
function foo() {
  console.log(value,'value');
}
function bar() {
 var value = 2;  foo(); } bar(); // Run the result // 1 "value" Copy the code

We analyze with the definition:

The bar function is executed, and a local scope is formed inside the function. Function foo does not have value in scope. It looks outward according to the rules of lexical scope. When this function is defined, foo’s outer scope is global and prints 1 if it is dynamically scoped: So it’s going to be 2, and I don’t know if you’re smart enough to figure that out

The global variable

var str = 'Global variable';
function func(){
  console.log(str+1);
  function childFn(){
    console.log(str+2);
 function fn(){  console.log(str+3);  };  fn();  };  childFn(); } func(); // Run the result // global variable 1 // global variable 2 // global variable 3 Copy the code

Let’s look at the following code:

var a = 100;
function fn(){
  a = 1000;
  console.log('a1---',a);
}
console.log('a2---',a); fn(); console.log('a3---',a); // Run the result // find variable a in the current scope => 100 // Global variable A has been reassigned when the function is executed // global variable a => 1000 Copy the code

Local scope

Local scopes are generally accessible only within fixed code snippets, most commonly in terms of functions:

function fn(){
  var name="Symbol";
  function childFn(){
    console.log(name);
  }
 childFn(); // Symbol } console.log(name); // name is not defined Copy the code

Scope chain

1. What are free variables

Let’s start by recognizing what a free variable is. In the following code, console.log(a) gets variable A, but a is not defined in the current scope (see b). Variables that are not currently defined in scope become free variables. How to get the value of the free variable – look for the parent scope (note: this is not strictly stated, but will be explained more carefully below).

var a = 100
function fn() {
  var b = 200
  console.log(a) // A here is a free variable here
  console.log(b)
} fn() Copy the code

2. What is scope chain

What if the parent doesn’t have either? Search up and down until you find the global scope. If you don’t find it, you give up. This layer by layer relationship is the scope chain.

var a = 100
function F1() {
  var b = 200
  function F2() {
    var c = 300
 console.log(a) // The free variable is traced to the parent scope  console.log(b) // The free variable is traced to the parent scope  console.log(c) // The variable of this scope  }  F2() } F1() Copy the code

3. The value of free variables

As for the value of a free variable, it is mentioned above that it should be taken from the parent scope. In fact, sometimes this interpretation will produce ambiguity.

var x = 10
function fn() {
  console.log(x)
}
function show(f) {
 var x = 20  (function() {  f() //10 instead of 20 }) ()} show(fn) Copy the code

In f sub n, what scope do I go to when I take the value of the free variable x? — to the scope in which the fn function was created, regardless of where the fn function will be called.

So don’t use that anymore. Instead, it would be more appropriate to say: go to the field where the function was created.

Scoped values, this is “create”, not “call”, remember — this is actually called “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

Scope and execution context

Many developers often confuse the concepts of scope and execution context, thinking they are the same, but they are not.

We know that JavaScript is an interpreted language, and the execution of JavaScript is divided into two stages: interpret and execute, which do different things:

Interpretation stage:

Parsing parsing scoping rules determine execution stages: Create execution context to perform function code garbage collection

The JavaScript interpretation phase determines the scope rule, so the scope is defined when the function is defined, not when the function is called, but the execution context is created before the function executes. The most obvious aspect of the execution context is that the reference to this is determined at execution time. The variables accessed by scope are determined by the structure of the code that was written.

The biggest differences between scope and execution context are:

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

A scope may contain several contexts. It is possible that there is never a context (the function is never called); It may have, but now the context is destroyed after the function is called; It is possible to have one or more at the same time. In the same scope, different calls will have different execution contexts, resulting in different variable values.