Анализ принципа прекомпиляции JavaScript

JavaScript

Во-первых, прекомпиляция JavaScript отличается от традиционной компиляции (прекомпиляцию js можно понимать как особый процесс компиляции)

  • Мы уже должны знать: JavaScript — это интерпретируемый язык. (интерпретируемый язык, то есть скомпилировать одну строку, выполнить одну строку)
  • Традиционная компиляция будет проходить через множество шагов, таких как сегментация слов, синтаксический анализ, генерация кода и т.д.
  • Позвольте мне поделиться с вами тем, что я понимаю о предварительной компиляции JS.

JavaScript запускает трилогиюСкрипт выполняет js, что делает движок?

  1. Разбор

Сначала просмотрите все это, чтобы увидеть, нет ли грамматических ошибок.

  1. Прекомпиляция (непосредственно перед выполнением)

подъем объявления переменной Общее продвижение объявлений функций

  1. объяснить исполнение

Интерпретировать строку выполнить строку

В функции: предварительно скомпилированное выполнение четверки

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

Глобально: предварительно скомпилированная трилогия

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

Анализ случая

<script>
    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);
</script>

Процесс анализа выглядит следующим образом:

  1. При генерации страницы создается глобальный объект GO (Global Object) (то есть объект окна);
  2. Загружается первый файл сценария;
  3. После загрузки скрипта проанализируйте, является ли синтаксис допустимым;
  4. начать предварительную компиляцию
  • Найдите объявление переменной, в качестве атрибута GO значение присвоено undefined;
  • Найдите объявление функции, как атрибут GO, значение присваивается телу функции;

После завершения глобальной прекомпиляции значение, хранящееся в GO

    //抽象描述
GO/window = {
        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() {}
        }
    }

Интерпретируйте и выполните код (пока не будет выполнен оператор test(2))

GO/window = {
        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() {}
        }
    }

Перед выполнением функции test() снова происходит прекомпиляция

根据函数中:预编译执行四部曲可知

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

//抽象描述
    AO = {
        a:undefined,
        b:undefined,
    }

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

 //抽象描述
    AO = {
        a:123,
        b:undefined,
    }

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

//抽象描述
    AO = {
        a:function a() {},
        b:undefined
        d:function d() {}
    }

Следующий процесс изменяется при выполнении функции test():

 //抽象描述
    AO = {
        a:function a() {},
        b:undefined
        d:function d() {}
    }
    --->
    AO = {
        a:123,
        b:undefined
        d:function d() {}
    }
    --->
    AO = {
        a:123,
        b:function() {}
        d:function d() {}
    }

Результаты:

QQ截图20210423225850.png

Уведомление:Объявления переменных и объявления функций происходят на этапе прекомпиляции, поведение присваивания отсутствует, а анонимные функции не участвуют в прекомпиляции, инициализация переменных выполняется только на этапе интерпретации и выполнения.

Раздел предварительной компиляции

  1. Два небольших правила прекомпиляции

    1. Общее продвижение объявлений функций - (независимо от того, находятся ли вызовы функций и объявления до или после, система всегда будет перемещать объявление функции впереди вызова)
    2. Продвижение объявления переменной - (независимо от того, вызывается и объявляется ли переменная до или после, система всегда будет перемещать объявление в начало вызова. Обратите внимание, что это только объявление, поэтому значение не определено)
  2. предварительно скомпилированная прелюдия

    1. То есть любой переменной, если ей присвоено значение без объявления, эта переменная принадлежит глобальной переменной. (Глобальный домен — Window)
    2. Все объявленные глобальные переменные являются свойствами окна, например: var a=12 эквивалентно Window.a = 12;
    3. Прекомпиляция функции происходит непосредственно перед ее выполнением.

Ссылка на ссылку

Ссылка на ссылку