Во-первых, прекомпиляция JavaScript отличается от традиционной компиляции (прекомпиляцию js можно понимать как особый процесс компиляции)
- Мы уже должны знать: JavaScript — это интерпретируемый язык. (интерпретируемый язык, то есть скомпилировать одну строку, выполнить одну строку)
- Традиционная компиляция будет проходить через множество шагов, таких как сегментация слов, синтаксический анализ, генерация кода и т.д.
- Позвольте мне поделиться с вами тем, что я понимаю о предварительной компиляции JS.
JavaScript запускает трилогиюСкрипт выполняет js, что делает движок?
- Разбор
Сначала просмотрите все это, чтобы увидеть, нет ли грамматических ошибок.
- Прекомпиляция (непосредственно перед выполнением)
подъем объявления переменной Общее продвижение объявлений функций
- объяснить исполнение
Интерпретировать строку выполнить строку
В функции: предварительно скомпилированное выполнение четверки
- Создать объект AO (Объект активации (контекст выполнения))
- Найдите объявление формального параметра и переменной, используйте имя переменной и формального параметра в качестве имени атрибута AO, а значение не определено.
- Унифицировать фактические и формальные параметры
- Найдите объявление функции в теле функции и присвойте значение телу функции.
Глобально: предварительно скомпилированная трилогия
- Создайте объект GO (окно Global Object является глобальным)
- Найдите объявление переменной, используйте объявление переменной в качестве имени атрибута объекта GO и присвойте значение неопределенному
- Найдите объявление функции в глобале, используйте имя функции в качестве имени атрибута объекта 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>
Процесс анализа выглядит следующим образом:
- При генерации страницы создается глобальный объект GO (Global Object) (то есть объект окна);
- Загружается первый файл сценария;
- После загрузки скрипта проанализируйте, является ли синтаксис допустимым;
- начать предварительную компиляцию
- Найдите объявление переменной, в качестве атрибута 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() {}
}
Результаты:
Уведомление:Объявления переменных и объявления функций происходят на этапе прекомпиляции, поведение присваивания отсутствует, а анонимные функции не участвуют в прекомпиляции, инициализация переменных выполняется только на этапе интерпретации и выполнения.
Раздел предварительной компиляции
-
Два небольших правила прекомпиляции
- Общее продвижение объявлений функций - (независимо от того, находятся ли вызовы функций и объявления до или после, система всегда будет перемещать объявление функции впереди вызова)
- Продвижение объявления переменной - (независимо от того, вызывается и объявляется ли переменная до или после, система всегда будет перемещать объявление в начало вызова. Обратите внимание, что это только объявление, поэтому значение не определено)
-
предварительно скомпилированная прелюдия
- То есть любой переменной, если ей присвоено значение без объявления, эта переменная принадлежит глобальной переменной. (Глобальный домен — Window)
- Все объявленные глобальные переменные являются свойствами окна, например: var a=12 эквивалентно Window.a = 12;
- Прекомпиляция функции происходит непосредственно перед ее выполнением.