变量提升和函数声明提升
var a = 1;
function fn() {
console.log(a); // undefined
var a = 2;
}
fn();
以上代码打印输出了undefined。
这就是变量声明提升-- 在全局作用域和函数作用域中声明的变量,会在预编译阶段被提升到代码头部。
所以相当于:
function fn() {
var a;
console.log(a); // undefined
a = 2;
}
接下来函数声明提升:
fn();
function fn() {
console.log(a);
let a = 2;
}
以上代码,可以正常执行,没有报错。
函数声明提升--在预编译阶段会将函数声明提升到该作用域顶部。所以在预编译阶段fn已经被挂载在window对象上了。
执行上下文对象
我们都知道,js代码执行分为三个阶段:语法分析、预编译,最后才是执行代码。
语法分析分为词法分析、转换为ast、转成机器语言。这里不作赘述。
那预编译阶段做了什么呢?
创建全局执行上下文对象
- 确认this指向全局执行上下文对象window
- 全局环境下声明的全局变量挂载在window上,值为undefined(变量声明提升)
- 全局环境下声明的全局函数挂载在window上,值为函数本身(函数声明提升)
创建函数执行上下文对象
- 确认this指向调用函数的对象
- 函数内声明的var变量,挂载在上下文对象上,值为undefined
- 函数内声明的函数声明,挂载在上下文对象上,值为函数本身
- 函数入参赋值,挂载在上下文对象上
- 创建执行上下文栈,用来存放执行中的执行上下文对象
执行上下文栈
用来存放执行上下文的栈,先入后出。