предисловие
Цель написания этого в том, что у автора всегда были сомнения по поводу продвижения переменных js.Простите меня за то, что я такой корявый ххххх
Когда происходит прекомпиляция
Прекомпиляция делится на глобальную прекомпиляцию и прекомпиляцию функции: глобальная прекомпиляция происходит при загрузке страницы, а прекомпиляция функции происходит непосредственно перед выполнением функции.
Шаги для глобальной прекомпиляции
- Создать объект GO (глобальный объект, глобальный контекст выполнения, окно в браузере);
- Найдите объявление переменной var и присвойте ей значение undefined;
- Найдите объявление функции function и назначьте его в качестве тела функции;
- Выполните код.
небольшой случай
Давайте сначала посмотрим на следующий код:
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{
// 对象内容为空
}
- Найдите объявление переменной var и назначьте его для undefined
Go{
x: undefined
y: undefined
z: undefined
}
- Найдите объявление функции function и назначьте его в качестве тела функции.
GO{
x: undefined
y: undefined
z: undefined
add: function add (n) { return n = n + 1; } => function add (n) { return n = n + 3; }
}
- выполнять код последовательно
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.
Шаги для предварительной компиляции функции
- Создайте объект AO, контекст выполнения (обновлено позже для подробного объяснения контекста выполнения).
- Найдите формальные параметры и объявления переменных функции, используйте имена переменных и формальных параметров в качестве имен свойств объекта AO и установите значение undefined.
- Унифицируйте формальный параметр и фактический параметр, то есть измените неопределенное значение формального параметра на конкретное значение формального параметра.
- Найдите объявление функции в функции, используйте имя функции в качестве имени атрибута 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);
Далее давайте подробно проанализируем его прекомпилированный процесс выполнения в соответствии с предыдущими шагами:
- Создать объект АО
AO{
// 空对象
}
- Найдите формальные параметры и объявления переменных функции, используйте имена переменных и формальных параметров в качестве имен свойств объекта AO и установите значение undefined.
AO{
a: undefined,
b: undefined
}
- Унифицировать формальные и фактические параметры
AO{
a: 1,
b: undefined
}
- Найдите объявление функции в функции, используйте имя функции в качестве имени атрибута 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);
- глобальная прекомпиляция
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() {}
}
}
- выполнять код последовательно
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() {}
}
}
- Выполнить для 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(){}
}
- Результаты
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 в коде, с которым вы столкнулись, вы можете проигнорировать его на этапе предварительной компиляции. Надеюсь, эта статья поможет вам, кто так же запутался, как и я!