Mo Yanmei takes you to read the world of “JavaScript you Don’t Know” series, get inside the JavaScript language, figure out the use of every part of JavaScript, and know why.

What is the scope

  • Question 1: Where are variables stored?
  • Question 2: How do I find them when the program needs them?

1.1 Compilation Principles

JavaScript is often classed as a “dynamic” or “interpreted execution” language, but in fact it is a compiled language, not compiled ahead of time, and compiled results are not ported to distributed systems.

The JavaScript engine compiles in much the same way as a traditional compiled language, and in some cases more complex.

In traditional compiled languages, the first three steps are collectively called “compile”.

  • Word Segmentation/Lexical Analysis (Tokenizing/Lexing)

    Breaking up a string of characters into blocks of code that make sense (to a programming language) is called lexical units (tokens).

    var a = 2;
    Copy the code

    Broken down into lexical units: var, a, =, 2; . Spaces that make sense in the language are treated as lexical units, not otherwise.

  • Parsing/Parsing

    The lexical unit stream (array) is converted into an Abstract Syntax Tree (AST) which is composed of elements nested step by step and represents the Syntax structure of the program.

    var a = 2;
    Copy the code

    The abstract syntax tree for the above code looks like this:

    • VariableDeclarationThe top node
      • IdentiferChild node, value isa
      • AssignmentExpressionChild nodes
        • NumericLiteralChild node, value is2
  • Code generation

    The process of converting an AST into executable code is called code generation. This process is language dependent, target platform dependent, and so on.

    Some way, var a = 2; The AST is converted to a set of machine instructions that create a variable, A, and store the value in A.

    Engine, which can create and store variables as needed.

1.2 Understand scope

1.2.1 cast

  • The engine, from start to finish, takes care of the whole thingJavaScriptThe compilation and execution of a program.
  • Compiler, responsible for syntax analysis and code generation and other dirty work.
  • Scope, which collects and maintains a series of queries made up of all declared identifiers (variables) and enforces a very strict set of rules that determine access to these identifiers by currently executing code.

1.2.2 dialogue

How does a JavaScript engine handle JavaScript code?

Var a = 2; There are two different declarations, and assignment to a variable performs two actions.

  • encountervar aAt compile time, the compiler first asks the current scope if there are any variables in the scope collectionaIf not, declare a new variable nameda; The compiler then generates code for the engine to run, processinga = 2This assignment operation.
  • Meet (a = 2In the execution phase, the engine runs by asking for scope and looking for the variable in scopea, if it finds the value2Assign to a variableaOtherwise, the engine raises its hand and throws an exception.

1.2.3 The compiler has something to say

  • How to understand the relationship between engine, compiler and scope

    • Code is compiled before it is executed, and when the compiler generates code in the second step of the compilation process, the engine executes it by looking up variablesaTo see if it’s already declared.
    • The lookup process is assisted by the scope, but how the engine performs the lookup affects the final result. rightJavaScriptEngine performance is very demanding.
  • Engine lookup in two ways: RHS and LHS

    • LHSQuery (left) : Find the container of the variable itself and assign to it the target of the assignment operation. Such asa = 2;for= 2The assignment operation finds a target.
    • RHSQuery (not left) : Finds the value of a variable, understood asretrieve his source valueThat is, who is the source of the assignment operation. Such as:console.log( a );, need to get the variableaOf the variableaRHSQuery and pass the value toconsole.log(...).
function foo(a){
	console.log( a ); //2
}
foo(2);
Copy the code

The above code has 1 LHS query and 3 RHS query.

  • LHSQueries are:
    • implicita = 2, in the2Is passed as a parameter tofoo(...)Function, you need to set parametersaforLHSThe query
  • RHSQueries are:
    • The last linefoo(...)The call to the function requires thefooforRHSQuery, which means”To find outfooAnd give it to me“And(...).meansfooIs required to be executed, so it had better really indicate the value of the function type.
    • console.log( a );In theaforRHSQuery, and pass the resulting value toconsole.log(...).
    • console.log(...)Itself toconsoleThe object ofRHSQuery and check if any of the resulting values is calledlogMethods.

1.3 Scope nesting

A scope is a set of rules for determining where and how to look for variables (identifiers). Nesting of scopes occurs when a block or function is nested within another block or function.

  • This is used if the purpose of the lookup is to assign a value to a variableLHSThe query; Used if the purpose is to get the value of a variableRHSThe query.
  • The assignment operator causesLHSThe query.=Operator or passing in an argument when calling a function results in an assignment of the associative scope.

The rule for traversing nested scope chains: The engine looks for variables from the current execution scope, and if it can’t find them, it looks up one level. When the outermost global scope is reached, the search process stops whether it is found or not.

1.4 abnormal

Why are LHS and RHS distinguished? The two queries behave differently when the variable has not yet been declared (it cannot be found in any scope).

function foo(a){
	console.log(a + b);
	b = a;
}
foo(2);
Copy the code

An RHS query on an “undeclared” variable B cannot find it in any of the relevant scopes.

ReferenceError is associated with scope discrimination failure, while TypeError is a reference to scope discrimination success, but the operation on the result is illegal or unreasonable.

  • RHSThe query does not find the desired variable in the scope chain, and the engine throws itReferenceErrorThe exception.
  • In the non-strict mode,LHSThe query does not find the desired variable in the scope chain, and a variable with that name is created in the global scope and returned to the engine.
  • In strict mode (ES5Start by disallowing automatic or implicit creation of global variables),LHSA failed query does not create and return a global variable, the engine throws the sameRHSSimilar when the query failsReferenceErrorThe exception.
  • inRHSIf the query is successful, the engine will throw an unreasonable operation on a variableTypeErrorThe exception. (Such as a function call or reference to a value that is not of a function typenullundefinedAttributes in the value of a type.

Finally, I read the book for hundreds of times, and with the original intention of teaching as learning, I constantly reflect and practice deliberately. If it is helpful to you, please give me a thumbs up. Thank you for your support and advice.

Reference: Mu Yi Yang’s blog

30 Seconds of ES6 (一)