Variable promotion (pre-parsing) :
Browsers will first ‘declare or define’ those with the ‘var’ or ‘function’ keyword before the js code in the current scope is executed from top to bottom.
Declare (declare) : var num; Declared in the current scope
Num =12; Append a value to a declared variable
Page loading only promotes variables in the global scope, regardless of variables in the private scope, and only promotes variables in the private scope within the function when the function is executed
The var keyword is just a reminder that there is no assignment;
The function keyword completes the declaration and definition in the variable promotion phase
Js code execution encountered create function code directly skip (not declare and do not assign operation) because variable promotion declaration and definition have been done
console.log(num) //=> undefined;
var num=13; //=> num = 13
console.log(num) //=> 13 At this point the code has been executed and the value is 13
console.log(fn) //=> fn(){
//console.log(a)
//var a=10;
//console.log(a)
/ /}
// The function keyword completes the declaration and definition in the variable promotion phase
fn(); //=> As long as the following, the preceding can also be executed because of the variable promotion
function fn(){ //=> Skip the code to create fn because variable promotion declaration and definition are done
// Private variables in private scopes are promoted at function execution
console.log(a) //=> undefined because the declaration is undefined
var a=10;
console.log(a) / / = > 10
}
fn()
Copy the code
Variables that have been declared will not be repeated. If they are declared again, they will be skipped
//=>1. var y; var z; fn=aaafff111;
var x=10,
y=20,
z=30;
function fn(x,y){
//=> Private scope
//=>3. Assign x=10 and y=20 (x/y are private variables) all xy variables within the function are private variables
Var x = 10; var x = 10; var x = 10
console.log(x,y,z) //=> 10 (private x) 20 (private y) 30 (z is global)
var x=100;// Private x=100, no var
y=200;// Private y=200
z=300;// global z=300
console.log(x,y,z) //100 (private x) 200 (private y) 300(z is a global variable)
}
fn(x,y,z) Fn (10,20,30); fn(10,20,30);
console.log(x,y,z) / / 10 20, 300
Copy the code
Variable promotion special case
1. How to define variables with and without var in the global scope
(1) If the current scope is global, var declares a variable and adds an attribute to the window global scope
(2) In the global scope without var just add an attribute to the window, but use the window. Omitted (not strictly a variable)
/ / var
console.log(a) //=> undefined
var a=10;
console.log(a) / / = > 10
console.log(window.a) / / = > 10
//不带var
console.log(a) //=> Error a is not defined
console.log(window.a) //=>undefined
a=12; // window. A =12
console.log(a) / / = > 12
console.log(window.a) / / = > 12
Copy the code
2. How to define variables with and without var in private scopes
- (1) In private scope,
Restart variable promotion with var
, declared as a private variable, has nothing to do with the outside world - (2)
Not a private variable without var
If the current scope is not declared, it will look up its parent scope to see if it is a parent variable. If it is, it will operate on the parent variable. - (3) Keep searching up until you find the window (we call this search mechanism:
"Chain of scope"
), window has, and operates on variables (attributes) of window - (4)
Window doesn't have one, so if it has an equal sign it adds a property to the window
If it doesn’t have an equal sign, it’s undefined, which meansDon't take the var
weIf the variable is not declared in a private scope, the operation is always someone else's
/ / var
function fn(){
console.log(a); //=>undefined
var a=12;
console.log(a); / / = > 12
}
fn();
console.log(a) //a is not defined closure mechanism (private scope protects private variables from external interference)
//不带var
function fn(){
console.log(a); //=> a is not defined
a=12;
console.log(a); //=> window
}
fn();
console.log(a) //=> window
Copy the code
The scope chain
Function execution forms a private scope (protected variables). When entering a private scope, the argument is promoted if the parameter is not assigned (declared variables are private), followed by code execution
1, execute a variable, if the variable is private, then treat it as private
function fn(){
console.log(a); //=>undefined
var a=12;
console.log(a); / / = > 12
}
fn();
console.log(a) // a is not defined // private scope protects private variables from external interference
Copy the code
2. If the current variable is not private, it needs to look up its parent scope. If it is not, it needs to look up until it finds the Window global scopeThe scope chain
- 1) If the parent scope does, we are currently operating on the parent scope variable (if we change the value in the current scope, it is equivalent to changing the value in the parent scope)
- 2) If the window is found, it does not have this variable; Variable = value:
This is equivalent to setting a property for the window
I’m going to use Windows in the future;But before the assignment, alert(variable) : wants to print this variable, which is not available, so an error is reported
function fn(){
console.log(a); //=> a is not defined
a=12;
console.log(a); //=> window
}
fn();
console.log(a) //=> window
Copy the code
sample
Var a; var b; fn=AAAFFF111
console.log(x,y) //=> undefined undefined
var x=10,y=20; //=> x=10,y=20
function fn(){
// Private scope variable promotion var x; (x private variable)
console.log(x,y) //=> undefined 20
var x=y=100; Var x=100 (private); Y =100 (global)
console.log(x,y) //=> 100 (private) 100 (global)
}
fn()
console.log(x,y) //=> 10 (global)
Copy the code
I only do variable promotion on the left-hand side
=: assign, the left side is a variable, the right side is always a value (whatever the right side is, the value must be calculated before assigning to the left side)
/ / before:
i%2= = =0? item.className='c1':item.className='c2'
/ / now,
item.className = i%2= = =0?'c1':'c2'
// Evaluate the operator to the left and assign it to the right
Copy the code
Anonymous function: function expression (assigning a function as a value to a variable or other content such as an event)
oDiv.onclick=function(){}
// this is equivalent to odiv. onclick = AAAFFF111.
Copy the code
Only the left side of the equals sign is promoted, and the right side of the equals sign is not pre-declared (even functions are not promoted).
console.log(fn) => undefinedVariable ascensionvarFn; = The value on the right is not variable promotedvar fn=function(){}
console.log(fn) => function itselfCopy the code
Declaring functions is bestFunctional expression
Var fn=function(){}
If a variable is promoted to the left of the equal sign, the current function is only declared and not defined. If the variable is promoted to the left of the equal sign, the current function can only be executed after the assigned code.
This makes our code logic a little bit more rigorous, and if you want to know what a function does, you can just look up the definition, right
sum(); //=> undefined sum is not a function
var sum=function(){}
sum(); / / = > is not an error
var fn=function sum(){ //==> Do not use this name
console.log(1)
}
sum(); / / = > an error
fn(); / / = > 1
var fn=function sum(){
console.log(sum) //=> Function itself
console.log(1)
}
fn(); / / = > 1
Copy the code
Preparse regardless of whether the condition is true or not
Var /function in the judgment body is promoted regardless of whether the condition is true or not
In newer browsers, the variable declared by function is declared only and cannot be defined (prerequisite: function must be in judgment body).
The function variable is promoted and defined regardless of whether the condition is valid
// New browser
console.log(num) => undefined
console.log(fn) => undefined
if(1= = =1) {// or if(1! = 1) have no effect on variable promotion
var num = 12;
function fn(){}}Copy the code
The code executes to the condition judgment
-
- 【
Conditions cannot be fixed
Not entering the body of judgment,The code for the assignment does not execute
At this time,Is still undefined
- 【
-
- 【
When the condition holds
Enter the body of judgmentThe first thing is not code execution
, butThe function that was not defined before the variable promotion was defined first
(The function is defined when you enter the judgment body
, to cater to es6 block-level scope)
- 【
-
- The function variable is promoted and defined regardless of whether the condition is valid
// Block level scope similar to ES6
console.log(num) => undefined
console.log(fn) => undefined
if(1= = =1) {// or if(1! = 1) have no effect on variable promotion
console.log(num) => undefined
console.log(fn) => function itselfvar num = 12;
function fn(){}console.log(num) => 12
console.log(fn) => function itself}console.log(fn) => undefined
for(var i=0; i<1; i++){// I <1 is also a condition
function fn(){}}Copy the code
case
//=> Variable promotion: No
f= function (){ return true; }; g=function (){ return false; }; ~function(){
//=> Private scope
//=> undefined (undefined) : undefined (undefined)
if(g() && [] == ! []) {// Errors are reported directly in newer browsers
// Older browsers g() is private true
/ /! []! Symbols are converted to Boolean
// [] == false
// the == operator compares different types of numbers first
/ / 0 = = 0
// true
//typeof [] //Object
//typeof ! [] //Boolean
f = function(){ return false}
function g(){
return true; }}} ()console.log(f()) => new version before error; The old versionfalse
console.log(g()) => error before new version; The old versionfalse
Copy the code
Variable promotion double name processing
In the variable promotion phase, ifThe name is duplicated and will not be redeclared
, butWill be redefined (usually refers to functions)
(Replace the preceding value with the following value)
After a function variable is promoted and defined, the code executes from the top down, and is no longer declared and defined when it encounters code that declares a function
//=> variable promotion:
1,var fn=aaafff111
2, fn = aaafff2223, do not perform any operation4, fn = aaafff3335, fn = aaafff444// => Code execution
fn() => 4
function fn(){ console.log(1)} / / ignore
fn() => 4
function fn(){ console.log(2)} / / ignore
fn() => 4
var fn=13; => fn=13 / / assignmentFn () => Error fn is not afunctionNo longer execute downfunction fn(){ console.log(3)}
fn()
function fn(){ console.log(4)}
fn()
Copy the code
Var is promoted to undefined not because the assignment is undefined but because it is undefined without the assignment
The default value is undefined
Only in the global scope do we declare a variable, which is equivalent to adding an attribute name to the global object Window
There is no variable promotion for LET in ES6
The browser does a repetition check (syntax check) before the current scope code executes from top to bottom
In ES6, for variables or functions created using LET/CONST, there is no variable promotion: the mapping between global variables and WINDOW properties is cut off
– You cannot declare variables with the same name in the same scope based on the let. No matter how a variable is declared in the current scope, an error will be reported if the variable is created using the let again.
ES6 also has scope chains
There is no variable promotion mechanism, but before the current scope code is executed from top to bottom, the browser does a repetition check (syntax check) : it looks up all the variables used in the current scope from top to bottom, and if it finds any duplication, it throws an exception and the code is not executed again
Although variables are not declared in advance, the browser already remembers which variables are created by lets in the current scope. Using variables before let will cause an error, as will assigning = before let
Check the syntax to see if a variable is created based on the new language, and if it is parsed according to the new syntax
If this variable is declared by the let below, the assignment and fetch before the let code will be an error
/ / the console. The log (a) an error
let a=12;
console.log(window.a) undefined
Copy the code
var a=12;
var a=13;
console.log(a) / / = > 13
let a=12;
let a=13; // Let cannot declare variables with the same name in the same scope
console.log(a) / / does not perform
let a=12;
console.log(a) // An error was reported that the same variable was verified before the code was executed
let a=13;
console.log(a)
a=12;// Error a is not defined because the browser remembers which variables in the current scope are created using let before let A
console.log(a)
let a=13;
console.log(a)
b=12;
console.log(b) / / 12
a=13// Error a is not defined because the browser remembers which variables in the current scope are created using let before let A
console.log(a)
let a=14;
console.log(a)
Copy the code
let a=10;
let b=10;
let fn = function(){
//console.log(a) //console.log(a) //console.log(a) //console.log(a) //console.log(a) // Console. log(a) // Console. log(a) // Console. log(a) // Console. log(a) // Console. log(a) // Console. log(a) // Console. log(a)
//a is a private scoped variable
////console.log(b) // Global 10
let a=b=20;
console.log(a,b) //=>(delete console.log) 20 Private 20 global
}
fn()
console.log(a,b) //=>(delete the first console.log) 10 global 20 Global
Copy the code
Temporary dead zones in JS
The variable is not available within the code block until it is declared using the let command. This is grammatically called a temporary dead zone (TDZ).
ES6 explicitly states that if there are let and const commands in a block, the variables declared by the block to those commands form a closed scope from the start.
Any time these variables are used before declaration, an error is reported.
In the original browser rendering mechanism (ES5), based on typeof and other logical operators to detect a variable has not been declared, will not report an error, return ‘undefined’;
If the current variable is handled based on ES6 syntax, using Typeof detection without declaring (before letting) will result in an error.
Creating a variable based on let treats most {} as a private block-level scope (similar to a function’s private scope). In this case, the syntax specification is rechecked to see if the variable was created based on the new language, and if it is resolved according to the new syntax specification
The {} following the if in ES6 forms a block-level private scope
Superior block-level scope is not superior scope (superior scope can only be formed by function execution)
var a=12;
if(true) {console.log(a) // error A is not defined (do not find the parent scope variable A)
let a=13; // Create a variable based on let, which treats most {} as a private block-level scope (similar to a function's private scope). In this case, check the syntax again to see if it is a variable based on the new language, and if it is parsed according to the new syntax
}
In ES6, {} after if forms a block-level private scope
Copy the code