1. Processing of variable and function declarations during compilation

JavaScript engines perform several optimizations at compile time, and some optimizations can quickly find identifiers during execution by statically analyzing the code and pre-determining where all variables and functions are defined and associating them with appropriate scopes. Therefore, the correct way to think about it is that all declarations, including variables and functions, are processed first before any code executes.

2. Various cases of variable promotion

2.1 Normal variables should be declared before being used

    var a = 'test';
    console.log(a); // test
Copy the code

The actual execution process is as follows:

   var a; // The variable definition is promoted to the top of the scope
   a = 'test' // The assignment is left in place
   console.log(a); //test
Copy the code

2.2 Use variables before variable declaration

    console.log(a); // undefined
    var a = "test";
Copy the code

If I get rid of variable declarations

    console.log(a);  // throw Error: Uncaught ReferenceError: a is not defined
Copy the code

Before the declaration of variable use, the actual execution process will do the following:

    var a;
    console.log(a); // undefined
    a = 'test';
Copy the code

2.3 Declare variables of the same name more than once

    // example 1
   var a=9;
   console.log(a);/ / 9
   var a;
   console.log(a);/ / 9
   // example 2
   var a=9;
   console.log(a);/ / 9
   var a=3;
   console.log(a); / / 3
Copy the code

Duplicate var declarations are ignored, but assignments and other operations remain.

2.4 Function declaration enhancement

   func(); //test
   function func(){
       console.log('test');
   }
Copy the code

The actual execution process is as follows:

   function func(){
        console.log('test');
   }
   test(); // test
Copy the code

2.5 Repeated function declarations

   func(); / / 2
   function func (){
       console.log(1);
   }
   function func(){
       console.log(2);
   }
Copy the code

Instead of repeating variable declarations, function declarations that appear later override previous ones, and the actual execution process does the following:

   function func (){
       console.log(1);
   }
   function func(){
       console.log(2);
   } // Override the previous function declaration
   func(); / / 2
Copy the code

2.6 Function declarations are promoted, but function expressions are not

   func(); // throw Error: Uncaught TypeError: func is not a function
   var func = function(){
       console.log(1)}Copy the code

The actual process is as follows:

   var func; // undefined
   func(); // Call error because undefined is not function
   func = function(){
       console.log(1)}Copy the code

2.7 Duplicate variable declaration and function declaration – function takes precedence

   /* example 1 */ 
   func(); // function
   var func= function(){
       console.log("variable")};function func(){
       console.log('function');
   }
   func();//variable
   
   /* example 2 */
   func(); //function
   function func(){
       console.log('function');
   }
   func(); // function
   var func= function(){
       console.log("variable")}; func();// variable
Copy the code

In actual execution, variable declarations are ignored, but assignments are reserved as follows:

   function func(){
       console.log('function');
   } // The function declaration is promoted
   func(); // function
   func(); // function
   /* var func; * / // The variable declaration is ignored
   func= function(){
      console.log("variable")}; func();// variable
Copy the code

2.8 Variable and function declarations inside ordinary blocks

   /* * Test environment * 1. Microsoft Edge 96.0.1054.41 * 2. Firefox 95.0.2 */
   // example 1
   console.log(typeof func); // undefined
   func(); // throw Error: Uncaught TypeError: func is not a function
   {
       function func() {
           console.log('a'); }}// example 2
   console.log(typeof func); // undefined
   func(); // throw Error: Uncaught TypeError: func is not a function
   
   var a =true;
   if(a){
       function func() {
           console.log('a'); }}else{
       function func() {
           console.log('b'); }}Copy the code

In the latest browsers, the rule of function declaration promotion inside the normal block has been changed, and the actual execution process looks like this:

   var func;
   console.log(func); // undefined
   func(); // throw Error: Uncaught TypeError: func is not a function
   {
       func = function() {
           console.log('a'); }}Copy the code

2.9 Internal variables, function declarations and formal parameter identifiers are the same

   function func(inner, val) {
       console.log(typeof inner, typeof val);
       function inner() {
           console.log(111);
       }
       var val=100;
       console.log(typeof inner, typeof val);
       inner();
   }

   func('test'.'test variable');
   func(function () {
       console.log(222);
   }, function () {
       console.log(333);
   })
    /* output * function string * function number * 111 * function function * function number * 111 */
Copy the code

Functions declared in the inner scope overwrite the arguments of the outer function. If an internally declared variable name is the same as a parameter, the declaration is ignored.

3 letwithconstImpact on declaration promotion

3.1 Block scope

   {
       let a='test';
   }
   console.log(a); // throw Error: Uncaught ReferenceError: a is not defined
Copy the code

Variables declared using the let and const keywords can only be used inside a block, not outside it.

3.2 It must be declared before use

   let a = 1;
   function test() {
       console.log(a);
       const a = 2;
   }
   test(); // throw Error: Uncaught ReferenceError: can't access lexical declaration 'a' before initialization
Copy the code

3.3 Variables or functions with the same identifier cannot exist in the same scope

   // example 1
   function test(params) {
       let params = 1;
   }
   test(0);// throw Error: Uncaught SyntaxError: redeclaration of formal parameter params
   
   // example 2
   function func() {
       let test = 1;
       let test = 3;
   }
   func();// throw Error: Uncaught SyntaxError: redeclaration of let test
   
   // example 3
   function func() {
       let inner=2;
       function inner (){
           console.log(111);
       }
   }
   func();// throw Error: Uncaught SyntaxError: redeclaration of let inner
Copy the code

3.4 classThe keyword is similar in declarationletandconst

   // example 1
   {
       class Test {}}var t1 = new Test();
   // throw Error: Uncaught ReferenceError: can't access lexical declaration 'Test' before initialization
   
   // example 2
   var t1=new Test();
   class Test{}
   // throw Error: Uncaught SyntaxError: redeclaration of let Test
   
   // example 3
   class Test{}
   var Test=1;
   // throw Error: Uncaught SyntaxError: redeclaration of class Test
Copy the code

Points to note:

  1. Only the declaration itself is promoted, and assignment or other arithmetic logic stays in place, not changing the order in which code is executed.
  2. Each scope is promoted.
  3. In practice, avoid repeated declarations, especially when common variables and function declarations are mixed together. Otherwise, many dangerous problems may ariseletandconstDeclare variables.