Прекомпиляция в Javascript

JavaScript

предисловие

Цель написания этого в том, что у автора всегда были сомнения по поводу продвижения переменных js.Простите меня за то, что я такой корявый ххххх

Когда происходит прекомпиляция

Прекомпиляция делится на глобальную прекомпиляцию и прекомпиляцию функции: глобальная прекомпиляция происходит при загрузке страницы, а прекомпиляция функции происходит непосредственно перед выполнением функции.

Шаги для глобальной прекомпиляции

  1. Создать объект GO (глобальный объект, глобальный контекст выполнения, окно в браузере);
  2. Найдите объявление переменной var и присвойте ей значение undefined;
  3. Найдите объявление функции function и назначьте его в качестве тела функции;
  4. Выполните код.

небольшой случай

Давайте сначала посмотрим на следующий код:

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)

Далее давайте подробно проанализируем его прекомпилированный процесс выполнения в соответствии с предыдущими шагами:
1. Создайте объект GO

GO{
    // 对象内容为空
}
  1. Найдите объявление переменной var и назначьте его для undefined
Go{
    x: undefined
    y: undefined
    z: undefined
}
  1. Найдите объявление функции function и назначьте его в качестве тела функции.
GO{
   x: undefined
   y: undefined
   z: undefined
   add: function add (n) { return n = n + 1; } => function add (n) { return n = n + 3; }
}
  1. выполнять код последовательно
var x = 1,
    y = z = 0;

function add (n) {
  return n = n + 1;
} //预编译环节已经进行了变量提升,故执行时不在看这行代码

y = add(x);
function add (n) {
  return n = n + 3;
}//预编译环节已经进行了变量提升,故执行时不在看这行代码,但是这一函数覆盖了前面的add函数

z = add(x)

Таким образом, наш объект GO становится

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

Таким образом, мы можем знать, что в это время значение x равно 1, значение y равно 4 и значение z равно 4.

Шаги для предварительной компиляции функции

  1. Создайте объект AO, контекст выполнения (обновлено позже для подробного объяснения контекста выполнения).
  2. Найдите формальные параметры и объявления переменных функции, используйте имена переменных и формальных параметров в качестве имен свойств объекта AO и установите значение undefined.
  3. Унифицируйте формальный параметр и фактический параметр, то есть измените неопределенное значение формального параметра на конкретное значение формального параметра.
  4. Найдите объявление функции в функции, используйте имя функции в качестве имени атрибута AO и значение в качестве тела функции.

небольшой случай

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(){};
 }
 
 //调用函数
 fn(1);

Далее давайте подробно проанализируем его прекомпилированный процесс выполнения в соответствии с предыдущими шагами:

  1. Создать объект АО
AO{
    // 空对象
}
  1. Найдите формальные параметры и объявления переменных функции, используйте имена переменных и формальных параметров в качестве имен свойств объекта AO и установите значение undefined.
AO{
    a: undefined,
    b: undefined
}
  1. Унифицировать формальные и фактические параметры
AO{
    a: 1,
    b: undefined
}
  1. Найдите объявление функции в функции, используйте имя функции в качестве имени атрибута AO и значение в качестве тела функции.
AO{
    a: function(){}
    b: undefined
    d: function(){}
}

Функция начинает выполняться последовательно построчно:

function fn(a){
    console.log(a);// 输出functiona(){}
    var a = 123;
    console.log(a);// 输出123
    
    function a(){};//预编译环节已经进行了变量提升,故执行时不在看这行代码
    console.log(a);// 输出123
    
    var b = function(){};//这个是函数表达式不是函数声明,故不能提升,会对AO中的b重新赋值
    console.log(b);//输出function(){}
    
    function d(){};
 }

Результат в комментарии блока кода

комплексный случай

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);
  1. глобальная прекомпиляция
GO{
    a: undefined,
    c: undefined,
    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() {}
    }
}
  1. выполнять код последовательно
GO{
    a: 1,
    c: function (){
        console.log("I at C function");
    },
    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() {}
    }
}
  1. Выполнить для test(2), функция начинает прекомпилироваться
  • 3.1
AO{
    a: undefined,
    b: undefined
}
  • 3.2
AO{
    a: 2,
    b: undefined
}
  • 3.3
AO{
    a: function(){},
    b: undefined,
    d: function(){}
}
  1. Результаты
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);

Суммировать

Если вы столкнетесь с проблемами, связанными с предварительной компиляцией в будущем, вы можете выполнить описанные выше шаги для их решения, и если у вас есть оператор if в коде, с которым вы столкнулись, вы можете проигнорировать его на этапе предварительной компиляции. Надеюсь, эта статья поможет вам, кто так же запутался, как и я!