(1) Preface

This article mainly introduces the execution of precompilation during JavaScript compilation, hoping to help you understand precompilation.

(2) Compilation and execution steps

Traditional compilation language compilation steps

For traditional compiled languages, the compilation steps are: lexical analysis -> syntax analysis -> code generation. Let’s take a look at these three processes.

  1. Lexical analysis

This separates the code into syntactic units, such as var a = 520; This code is usually broken down into four lexical units: var, a, =, 520.

  1. Syntax analysis

The process is to consolidate lexical units into a multidimensional array called an Abstract syntax tree (AST), as shown in the following code

if(typeof a == "undefined" ){ 
a = 0; 
} else { 
a = a; 
} 
alert(a);
Copy the code

When the JavaScript interpreter constructs a syntax tree and finds that it cannot, it raises a syntaxError and ends parsing the entire code block.

  1. Code generation

The process is to turn the ABSTRACT syntax tree AST into executable machine code that can be read and executed by a computer.

JavaScript Compilation Steps

A JavaScript engine is much more complex than a traditional three-step compiler for a language, but in general, the JavaScript compilation process consists of just three steps: 1. Syntax analysis 2. Precompile 3. Explain execution

(3) detailed explanation of precompilation

Precompiled Overview

JavaScript precompilation occurs a few microseconds (or less!) before the code snippet executes. , precompilation is divided into two types, one is function precompilation, the other is global precompilation, global precompilation occurs when the page is finished loading, function precompilation occurs at the moment before the function is executed. Precompilation creates the execution context for the current environment.

The precompilation of the function performs a tetralogy

  1. Create an Activation Object (hereinafter abbreviated as an AO Object);
  2. Look for the parameters and variable declarations, and take the variable declarations and parameters as the attribute names of the AO, with the values underpay;
  3. Unify argument and parameter values;
  4. Find the function declaration in the function body and assign the function name as the property name of the AO object.

Case code

// What does console.log() output below?
function fn(a) {
  //console.log(a);
  var a = 123// Variable assignment
  //console.log(a);
  function a() {}// Function declaration
  //console.log(a);
  var b = function () {}// Variable assignment (function expression)
  //console.log(b);
  function d() {}// Function declaration
}
fn(1)// Function call
Copy the code

After the code is annotated, we can easily see what the four console.log() outputs. Let’s look at the changes to the AO

  1. Creating an AO Object
AO{
    / / null objects
}
Copy the code
  1. Look for the parameters and variable declarations, and take the variable declarations and parameters as the attribute names of the AO, with the values underpay;
AO{
    a: undefined
    b: undefined
}
Copy the code
  1. Unify argument and parameter values;
AO{
    a: 1.b: undefined
}
Copy the code
  1. Find the function declaration in the function body and assign the function name as the property name of the AO object.
AO{
    a: function(){}
    b: undefined
    d: function(){}}Copy the code

Finally, here is the complete precompilation process

AO:{
a:underfined -> 1 -> function a(){}
b:underfined
d:function d(){}}Copy the code

Global precompilation executes the trilogy

  1. Create a Global Object (abbreviated to GO Object);
  2. Look for the parameters and variable declarations, and take the variable declarations and parameters as the attribute names of GO, and the values are underpay;
  3. Find the function declaration in the global, and assign the function name as the property name of the GO object with the value assigned to the function body.

Case code

global = 100;
function fn() {
  //console.log(global);
  global = 200;
  //console.log(global);
  var global = 300;
}
fn();
Copy the code

According to the global precompiled trilogy we can know his GO change process

  1. Create the GO object
GO{
    / / null objects
}
Copy the code
  1. Look for the parameter and variable declaration, and take the variable declaration and parameter as the property name of GO, with the value underpay
GO: {
  global: undefined
}
Copy the code
  1. Find the function declaration in the global, and assign the function name as the property name of the GO object with the value assigned to the function body
GO: {
  global: undefined
  fn: function() {}}Copy the code

Note that the function declaration brings in its own AO, and the precompilation process continues to use tetralogy

(4) Summary

You can use the above formula to get the correct answer to many questions that you might be asked about the console.log() output.