JavaScript deep understanding-scope

1. What is the scope?

1. Compilation Principle

JavaScript is a compiled language, not the so-called "dynamic" or "interpreted execution language". It is not compiled ahead of time, and the compiled results cannot be transplanted in a distributed system.
The compiled language executes the three previous steps:

1. Word segmentation/lexical analysis:

The character string is decomposed into meaningful code blocks, which are called lexical units. Example: var a = 3; In this process, it will be decomposed into the following lexical units: var, a, =, 3,;.

2. Analysis/Syntax analysis:

The stream of lexical units (array) is converted into a tree composed of gradually nested elements representing the grammatical structure of the program. This tree is called the "Abstract Syntax Tree" (AST).

3. Code generation

The process of transforming an abstract syntax tree (AST) into executable code.
The JavaScript engine is more than the above three steps, its steps are much more complicated.

note:

  • The JavaScript engine does not spend a lot of time for optimization (compared to other compiled languages ​​so much time), because the JavaScript compilation process does not happen before the build.
  • In most cases of JavaScript, compilation occurs a few microseconds before the code is executed, and any JavaScript code fragment will be compiled before execution.

2. Understanding the scope

Who is involved in JavaScript execution?

Engine : Responsible for the compilation and execution of the entire JavaScript program from start to finish.
Compiler : Responsible for syntax analysis and code generation.
Scope : Collect and maintain a series of queries composed of all identifiers (and variables), and implement a set of strict rules to determine the access rights of the currently executing code to these variables.

Two operations performed by variable assignment:

The compiler declares the variable in the current scope (if it has not been declared before).
The runtime engine will look for the variable in the scope, and if it finds it, it will assign a value.

The engine finds two types of variables:

LHS: The variable appears on the left side of the assignment operation to perform LHS query. (Find the target variable)
RHS: The variable appears on the right side of the assignment operation to perform RHS query. (Get its source value)

3. Scope nesting

When a block or function is in another block or function, nesting of scope occurs.
When a variable cannot be found in the current scope, the engine will continue to search in the outer nested scope until it finds the variable or reaches the outermost scope (global scope).

4. Abnormal

If the RHS query cannot find the required variable in all nested scopes, the engine will throw a ReferenceError exception .
If the LHS query cannot find the required variable in all nested scopes, it will create a variable with that name in the global scope and return it to the engine. (The program is in non-strict mode).
If the RHS query finds a variable, but you perform unreasonable operations on it, such as: making a function call to a value of a non-function type; referencing a property in a null or undefined type, the engine will throw a TypeError exception .

2. Lexical scope

The working model of scope: lexical scope and dynamic scope (used by a few programming languages).

1. What is lexical scope?

Lexical scope is determined by where you write variable and block scope when you write code. Therefore, the lexical analyzer will keep the scope unchanged when processing the code. This is what we call scope in JavaScript.

2. Scope lookup

The scope search will stop when the first matching identifier is found. Identifiers with the same name can be defined in multiple nested scopes (shading effect).
Note:
No matter where the function is called or how it is called, its lexical scope is only determined by the position where the function is declared.
Lexical scope only looks for first-level identifiers.

3. Deceptive Words

1. eval

The eval(...) function can accept a string as a parameter, and its content seems to exist in this position in the program when the code is written.
Example:

function foo(str, a) {
    eval(str) //欺骗的目的
    console.log(a, b);
}
var b = 2;
foo("var b = 3", 10); //执行结果10,3  

In the above code, b will not output 2 in the global scope. Because what is passed in is a var b = 3; when the eval function is executed, the code in eval will be executed, thus creating a variable b in the scope of the foo function. Thus obscuring b in the global scope.
Note: In strict mode, the eval(...) function has its own lexical scope at runtime, so the scope cannot be modified at this time.

2. with

with is usually used as a shortcut to repeatedly refer to multiple properties of the same object, without the need to refer to the object itself repeatedly.
Example:

function foo(obj) {
    with(obj){
        a = 2;
    }
}
var o1 = {
    a: 3;
}
var o2 = {
    b: 3;
}

foo(o1);
console.log(o1.a); //2
foo(o2);
console.log(o2.a) //undefined
console.log(a) //2

上述代码在执行13行时,将对象o1传进了函数foo,此时进行了with操作,里面的a=2,会在全局作用域中创建一个变量a,并把2赋值给它。

3. Performance

Seriously affect operating performance. (Don't use them)

Three, function scope

1. Basic concepts and usage

  1. Meaning : All global variables belonging to this function can be used and reused within the scope of the entire function (it can also be used in nested scopes).
  2. The identifier in the inner scope cannot be accessed in the outer scope. Identifiers in the outer scope can be accessed in the inner scope.
    Principle of Least Privilege (Minimum Authorization or Least Exposure Principle): In the software design process, the necessary content should be exposed to the minimum and other content should be "hidden", such as the API design of a certain module or object.
    The benefits of function scope : avoid conflicts between identifiers with the same name.
    How to effectively avoid conflicts :
  3. Global Namespace
    Use an object as the namespace of the library, and all functions that need to be exposed to the outside world will become attributes of this object (namespace), instead of exposing your own identifier to the top-level scope of this law.
  4. Module management
    Through the mechanism of the dependency manager, the library identifier is explicitly imported into another specific scope.

Function declaration and function expression:

  1. The function keyword is the first word in the declaration is the function declaration. Otherwise, it is a function expression.
  2. Function expressions can only be accessed in the inner scope, but not in the outer scope.
  3. Function expressions will not unnecessarily pollute the external scope.

2. Function category

  1. Anonymous function expression: no name identifier.
    Disadvantages :
    difficult to debug. The
    references themselves can only use the expired arguments.callee references.
    Code readability, poor understanding
  2. Immediately execute function expression (IIFE)
    form:
    (function foo(){…})()

Four, block scope

1. Block scope before ES6

1. with

The scope created from the object with with is only valid in the with statement and not in the outer scope.

2. try/catch

The catch clause creates a block-level scope, where the declared variables are only valid inside the catch.

2. Block-level scope added after ES6

1. let

The let keyword can bind a variable to any scope where it is located (usually inside {… }), that is, the let keyword implicitly hijacks the block scope where the variable it declares.
Example:

var foo = true;
if(foo){
    let bar = foo * 2;
    bar = something(bar);
    console.log(bar);
}
console.log(bar) //ReferenceError

The bar variable declared by let will report ReferenceError when accessed externally.
As long as the declaration is valid, a pair of curly braces {…} can be used anywhere in the declaration to create a binding block for let.
The let statement will not be promoted, that is, it will not be explained in advance like var.

2. const

Sonst was introduced in ES6, which can also be used to create block-scope variables whose values ​​are fixed (constants). Modifying its value after the definition will cause an error.

Five, scope enhancement

The engine compiles JavaScript code before interpreting it. Part of the compilation is to find all the declarations and associate them with the appropriate scope.
The process of scope promotion is as if variable and function declarations have been "moved" to the top from where they appear in the code. So there is a declaration first, and then an assignment.
Note :
Only the declaration itself will be promoted, and the assignment or other operating logic will stay in place. If the promotion changes the execution order of the code, it will cause very serious damage.
Each scope will be promoted. Function expressions will not be promoted.
Even with a named function expression, the name identifier cannot be used in the scope before it is assigned.

foo(); //TypeError(非法操作)
bar(); //ReferenceError(bar未声明)

var foo = function bar(){
    //...
}

After the promotion, you can see this form:

var foo;
foo(); //TypeError(非法操作)
bar(); //ReferenceError(bar未声明)

foo = function bar(){
    //...
}

Function first principle:
function declaration and variable declaration will be promoted. When both are present, the function is promoted first, and then the variable.

foo(); //1
var foo; //重复的声明(被忽略)
function foo(){
    console.log(1);
}
foo = function(){
    console.log(2);
}

Will output 1, not 2.
The above code is understood by the engine as:

function foo(){
    console.log(1);
}
foo(); //1
foo = function(){ 
    console.log(2);
}

Functions are promoted before variables.
The latter function declaration will overwrite the previous function declaration.

to sum up:

This article summarizes the scope of JavaScript in all aspects, starting from the principle of JS compilation, analyzing the execution process of JS code, and then introducing in detail the lexical scope, function scope, block scope, etc. of js, and finally the scope promotion is done Detailed analysis.
I hope this article can solve some of your problems and confusion. If there is anything wrong, point it out in time!

Guess you like

Origin blog.csdn.net/qq_41497756/article/details/108988637