preface

The purpose of writing this is that I have always been skeptical about js variable promotion, forgive me for being so pathetic

When does precompilation happen

Precompilation is divided into global precompilation and function precompilation: global precompilation occurs when the page is loaded, while function precompilation occurs just before the function is executed.

Steps for global precompilation

  1. Create GO (Global Object, window in browser) Object;
  2. Find the var variable declaration and assign it to undefined;
  3. Find the function declaration and assign it to the function body;
  4. Execute the code.

A small case

Let’s take a look at the following code:

var x = 1,
    y = z = 0;

function add (n) {
  return n = n + 1;
}

y = add(x);
function add (n) {
  return n = n + 3;
}

z = add(x)
Copy the code

Next, we will analyze its precompiled execution process in detail by following the previous steps: 1. Create a GO object

GO{
    // The object content is empty
}
Copy the code
  1. Find the var variable declaration and assign it to undefined
Go{
    x: undefined
    y: undefined
    z: undefined
}
Copy the code
  1. Find the function declaration and assign it to the function body
GO{
   x: undefined
   y: undefined
   z: undefined
   add: function add (n) { return n = n + 1; } = >function add (n) { return n = n + 3; }}Copy the code
  1. Execute code sequentially
var x = 1,
    y = z = 0;

function add (n) {
  return n = n + 1;
} // This line of code will not be read when executing the precompile because the variable promotion has already been performed

y = add(x);
function add (n) {
  return n = n + 3;
}// This function overrides the previous add function

z = add(x)
Copy the code

So our GO object becomes

GO{
   x: 1
   y: 0
   z: 0
   add: function add (n) { return n = n + 3; }}Copy the code

So we know that x is equal to 1, y is equal to 4, and z is equal to 4

Steps in function precompilation

  1. Create an AO object with an execution-time context (more on this later).
  2. Look for the function’s parameter and variable declarations and use the variable and parameter names as the attribute names of the AO object, with the value set to undefined.
  3. Unify a parameter with an argument by changing undefined to a specific parameter value.
  4. Find the function declaration in the function, using the function name as the AO property name and the value as the function body.

A small case

function fn(a){
    console.log(a);
    var a = 123;
    console.log(a);
    
    function a(){};
    console.log(a);
    
    var b = function(){};
    console.log(b);
    
    function d(){};
 }
 
 // Call the function
 fn(1);
Copy the code

Let’s analyze its precompiled execution process in detail by following the previous steps:

  1. Creating an AO Object
AO{
    / / null objects
}
Copy the code
  1. Look for the function’s parameter and variable declarations and use the variable and parameter names as the attribute names of the AO object, with the value set to undefined.
AO{
    a: undefined.b: undefined
}
Copy the code
  1. Unifies parameters and arguments
AO{
    a: 1.b: undefined
}
Copy the code
  1. Find the function declaration in the function, using the function name as the AO property name and the value as the function body.
AO{
    a: function(){}
    b: undefined
    d: function(){}}Copy the code

The function starts execution line by line:

function fn(a){
    console.log(a);/ / output functiona () {}
    var a = 123;
    console.log(a);/ / output 123
    
    function a(){};// This line of code will not be read when executing the precompile because the variable promotion has already been performed
    console.log(a);/ / output 123
    
    var b = function(){};// This is a function expression, not a function declaration, so it cannot be promoted
    console.log(b);/ / output function () {}
    
    function d(){};
 }
Copy the code

The result is in the comment of the code block

A composite case

var a = 1;
console.log(a);
function test(a) {
  console.log(a);
  var a = 123;
  console.log(a);
  function a() {}
  console.log(a);
  var b = function() {}
  console.log(b);
  function d() {}}var c = function (){
console.log("I at C function");
}
console.log(c);
test(2);
Copy the code
  1. Global precompilation
GO{
    a: undefined.c: undefinedThe test:function(a) {
        console.log(a);
        var a = 123;
        console.log(a);
        function a() {}
        console.log(a);
        var b = function() {}
        console.log(b);
        function d() {}}}Copy the code
  1. Execute code sequentially
GO{
    a: 1.c: function (){
        console.log("I at C function"); }, the test:function(a) {
        console.log(a);
        var a = 123;
        console.log(a);
        function a() {}
        console.log(a);
        var b = function() {}
        console.log(b);
        function d() {}}}Copy the code
  1. At test(2), the function is precompiled
  • 3.1
AO{
    a: undefined.b: undefined
}
Copy the code
  • 3.2
AO{
    a: 2.b: undefined
}
Copy the code
  • 3.3
AO{
    a: function(){},
    b: undefined.d: function(){}}Copy the code
  1. The execution result
var a = 1;
console.log(a); / / 1
function test(a) {
  console.log(a); // function a() {}
  var a = 123;
  console.log(a); / / 123
  function a() {}
  console.log(a); / / 123
  var b = function() {}
  console.log(b); // function b() {}
  function d() {}}var c = function (){
console.log("I at C function");
}
console.log(c); // function c(){ console.log("I at C function"); }
test(2);
Copy the code

conclusion

If there is an if statement in your code, ignore it during the precompilation phase. I hope this article helps you who are as confused as I am!