This is the 17th day of my participation in the August Text Challenge.More challenges in August
compile
A piece of source code in a program goes through three steps before execution:
- Word segmentation/lexical analysis
- Parsing/parsing
- Code generation
Lexical analysis
This process breaks down a string of characters into blocks of code that make sense (to the programming language), called lexical units (tokens). For example, consider the program var a = 2; . The program is usually broken down into the following lexical units: var, a, =, 2; . Whether Spaces are considered lexical units depends on whether they make sense in the language.
Syntax analysis
This process converts a stream of lexical units (arrays) into a hierarchical nested tree of elements that represents the syntactic structure of the program. This tree is called an Abstract SyntaxTree (AST). var a = 2; The abstract syntax tree may have a top-level node called VariableDeclaration, followed by a child node called Identifier (whose value is A), and a child node called AssignmentExpression. The AssignmentExpression node has a child called NumericLiteral (whose value is 2).
Code generation
The process of transforming an AST into executable code is called code generation. This process depends on language, target platform, and so on. Regardless of the details, the short answer is that there is some way to set var a = 2; The AST is converted to a set of machine directives that create a variable called A (including allocating memory, etc.) and store a value in A.
These are the three steps your code must go through in the compiler, but a JavaScript engine is much more complex. For example, there are specific steps in the parsing and code generation phases to optimize runtime performance, including for redundant elements.
Scope understanding
For code that operates on variables, the compiler queries the scope chain for whether the variable has been created according to specific rules.
LHS query
Occurs when a variable appears to the left of an assignment operationRHS query
Occurs when a variable appears to the right of an assignment
Take a chestnut
function foo(a) {
console.log( a ); / / 2
}
foo( 2 );
Copy the code
- The last line
foo(..)
The call to the function requires thefoo
forRHS
The query foo
In a function declarationa = 2
Is an implicitLHS
The query,2
Is passed as a parameter tofoo(..)
Function,2
Will be assigned to parametersa
console.log( a )
forconsole
The object ofRHS
Query and check if any of the resulting values is calledlog
The method of
Scope nesting
Nesting of scopes occurs when a block or function is nested within another block or function. Therefore, when a variable cannot be found in the current scope, the engine will continue searching in the outer nested scope until it finds the variable or reaches the outermost scope (that is, the global scope).
The rule for traversing a nested scope chain is simple: The engine looks for variables starting at the current execution scope, and if it doesn’t find any, it continues up one level. When the outermost global scope is reached, the search process stops whether it is found or not.
abnormal
It is important to distinguish between LHS and RHS correctly
The two queries behave differently when the variable has not yet been declared (it cannot be found in any scope).
function foo(a) {
// the current scope, b is not created, engine back to the previous scope to find
console.log( a + b );
b = a;
}
// Here is the top-level scope
// If the engine still does not find B, a variable b individual engine is created in the global scope
// Only in non-strict mode
foo( 2 );
Copy the code
Instead of creating and returning a global variable when an LHS query fails in strict mode, the engine throws a ReferenceError exception similar to that when an RHS query fails.
If an RHS query finds a variable and you try to manipulate the value of the variable improperly, such as trying to make a function call on a value that is not of a function type, or referring to an attribute in a value of type null or undefined, the engine will raise another type of exception called TypeError.
ReferenceError indicates that the related variable was not found in the scope chain, and TypeError indicates that the related variable exists in the scope chain, but was improperly operated on, that is, an operation was performed on the variable that did not correspond to its type.
conclusion
- This is used if the purpose of the lookup is to assign a value to a variable
LHS
The query - Used if the purpose is to get the value of a variable
RHS
The query - The assignment operator causes
LHS
The query =
The operator causes bothLHS
Queries can also lead toRHS
The queryLHS
和RHS
The query will start in the current execution scope- If the relevant variable is not found in the current scope, it is queried one level up, all the way to the top-level scope
- After reaching the top-level scope, in non-strict mode, the related global variable cannot be found, and in strict mode, the related global variable will be generated automatically
ReferenceError
- When a query reaches the top-level scope, it stops regardless of the result of the query.