JavaScript is a single-threaded, interpreted, weakly typed, dynamic language that interprets line by line.

JavaScript execution process first parsing, is to analyze the code for syntax errors, parsing will not execute the code. And then you start precompiling, and then you start executing the code line by line.

The precompilation process creates two objects, a Global Global Object, abbreviated GO, and a function Activation Object, abbreviated AO. The two are only scoped differently and the creation steps are the same.

The steps for precompiling are as follows:

Create AO and GO objects

Find the parameter and variable declaration, as the property name, with the value undefined

Unify arguments and parameters

Find the function declaration, assign the function body

Let’s take a function as an example:

function fn(a) {

console.log(a);

var a = 1;

console.log(a);

function a() {};

console.log(a);

var b = function () {};

console.log(b);

function c() {}

}

fn(3);

Create AO = {}

Take parameter and variable declarations as attribute names and assign undefined

AO = {

A: undefined,// a var a function a

b: undefined,//var b

c :undefined,//function c

}

Unify parameters and arguments

AO = {

a: 3,

b: undefined,//var b

c :undefined,//function c

}

Find the function declaration, assign the function body

AO = {

a: function a(){},

b: undefined,//var b

c: function c(){},

}

And then line by line:

function fn(a) {

console.log(a);

var a = 1;

console.log(a);

function a() {};

console.log(a);

var b = function () {};

console.log(b);

function c() {}

}

fn(3);

AO = {

a: function a(){},

b: undefined,

c: function c(){},

}

When I print the first one, I print function, and then var a = 1, it’s already declared, it’s actually a = 1, so I print the second one, it’s already declared by the time I print function A, it’s already declared by the time I print it, it’s also going to be 1, and I don’t need to say more about b and C. The final result is f a(){}, 1, 1, f(){}.

A couple of things to keep in mind is that function declarations are an overall promotion, and variable declarations are just declarations of promotion. Also, if a variable is not declared, the default is window:

(function fn() {

var a = b = 10;

} ());

console.log(b); / / 10

console.log(a); //err

B does not have a direct var declaration, so it is a global window, so b can print, A will report an error.

It is important to note that JavaScript interprets function declarations during precompilation, but ignores table expressions. For example, a self-executing function:

(function fn() {

} ())

When an expression is executed with (), JavaScript evaluates the expression to get the return value. It returns a function with (), so it executes directly. All other self-executing functions work the same way. The grouping operator () is not required to convert a function to an expression. We can also use the void operator,! Operator + operator and so on.

+function () {}()

void(function () {alert(0)}())

console.log(function () {alert(0)}())

Each of these expressions executes the function immediately, even if the + sign results in a NaN, but the function must be executed before the implicit conversion.

You can think of the function as implicitly declaring a variable a:

function fn(a) {

var a;

console.log(a); / / 3

}

fn(3)

In addition, a temporary scope is formed in the function argument during the precompilation process, and will disappear after the precompilation:

function fn(a, b = function () {a = 5}) {

console.log(a); / / 3

b();

console.log(a); / / 3

}

fn(3)

(a, b = function () {a = 5}) this is a temporary scope. This works only in the scope of the argument:

function fn(a, b = (function () {a = 5})()) {

console.log(a); / / 5

console.log(a); / / 5

}

fn(3)