1.1. Compilation principle

Js is often referred to as a “dynamic” or “interpreted execution” language, but in fact it is a compiled language, which is very similar to traditional compilation, or even more complex.

In general, traditional compiled languages go through three steps:

  • 1. Word segmentation/morphology analysis

  • Parsing/parsing

  • Code generation

Js compilation usually takes place a few microseconds before execution.

1.2. Understand the scope

The first thing to remember is that there are three roles involved in the compilation process: the engine, the compiler, and the scope

The engine is responsible for compiling and executing the entire code, the compiler is responsible for parsing and code generation, and the scope collects and maintains all declared identifiers.

For example:

var a = 2;
Copy the code

The compiler first looks at the scope and asks if it has a variable named A, then ignores it, otherwise it lets the scope declare,

The compiler then generates code for the engine to run, which is a = 2; (In other words, the variable declaration is done by the compiler, the engine only needs to do the assignment.)

The engine then goes to work, it finds the scope and asks if variable A exists, if it does, it uses the variable, otherwise it continues to look up the parent scope (explained in scope nesting in 1.3).

Eventually the engine will assign if a is found, otherwise it will throw an exception.

Summary: the compiler is responsible for declaring variables, and the engine is responsible for finding declared variables to use.

1.3. Engine query mode

First of all, the engine is divided into LHS and RHS query methods, L and R can be understood as the left and right side of assignment operation.

In other words, when assigning a variable, perform an LHS query, such as a = 2; RHS queries are performed when variable value lookups are performed. Such as the console. The log (a); In this case, user A needs to perform RHS query.

Note: This definition of query rules does not apply when a function is declared. Function foo (a) {… }, normally understood as var foo; foo = func… In fact, the compiler has already processed foo’s declaration and value definition at the same time as the code is generated, so when the engine executes the code, no assignment is performed on Foo and no LHS query is generated.

1.4. Scope nesting

Scoped nesting occurs when a block or function is in another block or function, and when the engine cannot find a variable in the current scope, it looks up until it finds that variable or reaches the global scope. This is true for both LHS and RHS.

ReferenceError is raised when an RHS query does not find the specified variable in all nested scopes, while an LHS query does not find the specified variable in the global scope and returns it to the engine (non-strict mode).

If RHS finds a variable but does something inappropriate to it (such as executing a non-functional variable), TypeError is thrown.

That is, ReferenceError is related to scope discrimination failure, while TypeError represents scope discrimination success, but the operation is illegal.

To sum up these details, it is very important to distinguish BETWEEN LHS and RHS.

Quiz:

Please find three LHS and four RHS in the following code.

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