前言
-
为什么
var声明的变量可以先访问后定义? -
为什么函数可以在声明前调用?
-
为什么
let会出现暂时性死区?
这些问题背后,都和 执行上下文、变量提升 有关。
一、什么是执行上下文?
执行上下文可以简单理解为:
JavaScript 代码执行时所在的环境。
JavaScript 在执行代码时,并不是简单地一行一行执行,它会先创建执行上下文,然后再执行代码。
二、执行上下文的类型
主要有三种:
-
全局执行上下文
-
函数执行上下文
-
eval执行上下文(较少用)
三、什么是变量提升?
变量提升指的是:
变量和函数的声明,会在代码执行前被处理。
例如:
console.log(a);
var a = 10;
看起来像是先访问后声明,但不会报错,而是输出:
undefined
因为它大致相当于:
var a;
console.log(a);
a = 10;
这就是变量提升。
四、函数提升
函数声明也会提升,而且优先级通常高于var。
sayHello();
function sayHello() {
console.log('hello');
}
这段代码可以正常执行。
五、var 和 function 的区别
console.log(a); // undefined
var a = 10;
foo(); // foo
function foo() {
console.log('foo');
}
原因:
-
var只提升声明,不提升赋值
-
function会整体提升
六、let / const 为什么不能先访问?
console.log(a);
let a = 10;
这里会报错。
因为let和const虽然也会在作用域开始时被“记录”,但在正式声明前不能访问,这段区域称为:
暂时性死区(TDZ)
七、执行上下文大致过程
执行上下文可以粗略理解为两个阶段:
1)创建阶段
-
建立作用域
-
处理
this -
收集变量和函数声明
2)执行阶段
- 按顺序执行代码
- 完成赋值
- 调用函数
八、总结
执行上下文和变量提升是理解 JavaScript 执行机制的重要基础。
重点记住:
-
var提升声明,不提升赋值
-
function整体提升
-
let / const有暂时性死区
-
JavaScript 会先创建执行上下文,再执行代码