JS Compilation Principles#
var name = "rose";
The above line of code is presented in JS as follows:
var name; // processed during compilation phase
name = "rose"; // processed during execution phase
JS compilation is mainly divided into two phases: compilation phase and execution phase.
Compilation Phase#
The main character in this phase is the compiler.
- JS searches the scope to see if the variable
name
exists.- If it already exists, it does nothing and ignores the
var name
declaration, continuing with the compilation. - If it doesn't exist, it adds a new
name
variable to the current scope.
- If it already exists, it does nothing and ignores the
- The compiler generates the code required by the engine at runtime, and the program enters the execution phase.
Execution Phase#
The main character in this phase is the JS engine.
- During runtime, the JS engine first searches the current scope to see if there is a variable named
name
.- If it exists, it assigns a value to it.
- If it doesn't exist, it checks the parent scope to see if it exists there. If not, it continues to search in the higher-level scope.
- If it is not found in any scope, an exception is thrown.
Scope within scope, known as scope chain.
Scope#
The most basic ability of a variable is to store values and allow us to access and modify them, and the rules for storing and accessing variables are called scope.
Global Scope#
The top-level scope outside any function or code block is the global scope, and the variables inside it are global variables.
var name = "rose"; // global scope
function showName() {
// function scope
console.log(name);
}
{
name = "test"; // block scope
}
showName(); // test
As you can see, global variables can be accessed normally in the global scope, function scope, and block scope.
Function Scope#
The scope inside a function is the function scope.
function showName() {
var name = "jack"; // function scope
}
showName(); // method call
{
console.log(name); // block scope, Uncaught ReferenceError: name is not defined
}
console.log(name); // global scope, Uncaught ReferenceError: name is not defined
As you can see, variables inside a function cannot be accessed in the global scope or block scope. They can only be accessed within the function, so variables inside a function are also called local variables.
Block Scope#
The let
and const
keywords introduced in ES6
have their own scope.
Variables declared with const
in a code block are also known as local variables.
{
let name='rose';
}
console.log(name); //Uncaught ReferenceError: name is not defined
function showName{
console.log(name);
}
showName(); //Uncaught ReferenceError: name is not defined
As you can see, variables in a block scope cannot be accessed outside the code block.
Scope Chain#
The nesting of scopes creates a scope chain. The scope chain is searched from outside to inside.
Variable Hoisting#
name = "rose";
console.log(name); // rose
var name;
It can be observed that this code can run normally without any errors.
In the eyes of JS, the code is actually like this:
var name;
name = "rose";
console.log(name); // rose
let
and const
code:
name = "rose";
console.log(name); // Uncaught ReferenceError: Cannot access 'name' before initialization
let name;
let
andconst
disable variable hoisting.const
must be assigned a value after declaration.
Differences between let, const, and var#
- Block Scope: Block scope is created by
{}
.let
andconst
have block scope, whilevar
does not.
Block scope solves two problems in ES5:
- Inner variables may overwrite outer variables.
- Loop variables used for counting leak into the global scope.
-
Variable Hoisting:
var
variables are hoisted, whilelet
andconst
variables are not hoisted, meaning that variables can only be used after they are declared, otherwise an error will occur. -
Adding Properties to the Global Object: The global object in browsers is
window
, and in Node.js it isglobal
. Variables declared withvar
become global variables and are added as properties to the global object, butlet
andconst
variables are not. -
Redeclaration:
var
allows variables to be redeclared in the same scope, with the later declaration overwriting the earlier one.let
andconst
do not allow variables to be redeclared in the same scope. -
Temporal Dead Zone: When using
let
orconst
to declare variables, the variables are not accessible until they are initialized. This is known as the temporal dead zone.
Variables declared with var
do not have a temporal dead zone.
-
Initial Value:
var
andlet
can be declared without assigning an initial value, whileconst
requires an initial value to be assigned. -
Pointer Assignment: Variables created with
let
can have their pointer reassigned (can be reassigned), but variables created withconst
cannot have their pointer reassigned (cannot be reassigned).
Temporal Dead Zone#
var name = "rose";
{
name = "bob";
let name; // Uncaught ReferenceError: Cannot access 'name' before initialization
}
If there is let
or const
in a block, the block forms a closed scope for variables declared with these keywords from the beginning.
Because JS is aware that name
is declared with let
in the current code block, it adds the restriction of the temporal dead zone to this variable name
, and it doesn't stick its head out.
Therefore, if we remove the let name;
above, the program can still run normally, and the value of name
can be successfully changed to bob
, which means it sticks its head out normally according to the rules of the scope chain.