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 varIf 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 windowIf it doesn’t have an equal sign, it’s undefined, which meansDon't take the varweIf 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 windowI’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 expressionVar fn=function(){}

  1. 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.

  2. 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

    1. Conditions cannot be fixedNot entering the body of judgment,The code for the assignment does not executeAt this time,Is still undefined
    1. When the condition holdsEnter 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)
    1. 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