JavaScript is a descriptive scripting language, which is different from java or C# and other compiled languages. It does not need to be compiled into an intermediate language, but by browser Dynamically parse and execute. The code cannot be run directly. It needs to be compiled by the JavaScript compiler. Only the compiled code can be recognized, and then the code logic can be executed by the JavaScript engine.
give an example:
var a = 2;
1, Compile
1. Participle:
The purpose of word segmentation is to decompose these codes into meaningful code blocks, which are called lexical units.
var a = 2; // Will be decomposed into 'var, a, =, 2,;' These lexical units form an array of lexical unit streams // Results after lexical analysis [ "var" : "keyword", "a" : "identifier", "=" : "assignment", "2" : "integer", ";" : "eos" (end of statement) ]
2. Analysis:
Parse the code blocks just obtained from word segmentation to produce an abstract syntax tree;
(abstract syntax tree (AST) converts the lexical unit stream array into a tree composed of nested elements to represent the program syntax structure.)
Program body[1]:{ // Representative code is a program Variable Declaration:{ // Variable declaration declarations[1]:{ // Declaration array Variable Declaration:{ // Variable declaration id:{ // Variable name Identifier:{ // identifier name: a } }, init: { // Initialization operation Literal: { value: 10, raw: 10 } } } }, kind:var // Representative type } }
3. Code generation:
The process of converting AST into executable code is called code generation.
The JavaScript engine will convert the abstract syntax tree generated in the second step into executable code (machine instructions) to create a variable called a (including memory allocation), and store the value 2 in a.
2, Execute
1. Execution principle:
1.1 when the engine runs, it will first query the scope to see if there is a variable called a in the current scope collection.
If so, the engine will use this variable;
If not, the engine will continue to find the variable, and will continue to find the target identifier from the superior operation domain. In this way, each time the operation domain rises one level, and finally reaches the global operation domain (top level), it will abort whether it is found or not.
1.2 if the engine finally finds the variable a, it will assign 2 to it, otherwise the engine will throw an exception.
1.3 two methods of variable query: LHS and RHS
-
RHS query is no different from simply finding the value of a variable, while LHS query is trying to find the container of the variable itself so that it can be assigned a value. From this point of view, RHS is not really the "right side of assignment operation", more accurately, it is a "non left side" function
-
LHS and RHS mean "left or right side of assignment operation" and do not necessarily mean "= left or right side of assignment operator". There are other forms of assignment operation, so it is better to conceptually understand it as "who is the target of assignment operation (LHS)" and "who is the source of assignment operation (RHS)".
Attention
-
LHS and RHS queries will start in the current execution domain. If necessary (that is, they do not find the required identifier), they will continue to find the target identifier from the superior domain. In this way, each time they rise one level of the domain (one floor) and finally reach the global domain (top floor), they will stop whether they are found or not. An unsuccessful RHS reference causes a ReferenceError exception to be thrown. An unsuccessful LHS reference causes a global variable to be automatically and implicitly established (in non strict mode)
-
Lookup only looks for first level identifiers, such as a, b, and c. If foo.bar.baz is referenced in the code, the lexical domain search will only try to find the foo identifier. After finding this variable, the object attribute access rule will take over the access to bar and Baz attributes respectively.
-
If the RHS query finds a variable, but you try to perform unreasonable operations on the value of this variable, such as trying to make a function call on a value of non function type, or referencing the attribute in the value of null or undefined type, the engine will throw another type of exception, called TypeError.
a = 2; console.log(a); // 2 automatically create a global variable
console.log(a) // When the undefined console.log statement is executed, var a=function has not been executed, but Yes, all the code has been compiled, so the variable a has been placed in memory var a = function () { document.write("hellow world!") } console.log(apple); // ReferenceError: apple is not defined var b; console.log(b); // undefined
a (); // TypeError: a is not a function is stored by compiling variable a, but it is not assigned as a function Number is not a function type, so calling function a is to perform unreasonable operations on variables var a = function () { document.write("hellow world!") }
var b; b = a; console.log(b); // ReferenceError: a is not defined