08 JS如何实现块级作用域
总结
块级作用域就是通过 词法环境 的栈结构来实现的,而变量提升是通过变量环境来实现
块级作用域
作用域:指在程序中定义变量的区域,该位置决定了变量的生命周期。
变量提升的缺陷:
- 变量容易在不被察觉的情况下被覆盖掉
- 本应销毁的变量没有被销毁
ES6通过引入块级作用域并配合 let
、const
关键字解决 变量提升 的问题,作用块内声明的变量不影响块外面的变量。
块级作用域的实现
从执行上下文角度看块级作用域的实现(以let为例):
function foo(){
var a = 1
let b = 2
{
let b = 3
var c = 4
let d = 5
console.log(a) // 1
console.log(b) // 3
}
console.log(b) // 2
console.log(c) // 不是undefined -> 是4,这个要尤其注意,var在变量环境中预编译时已存在
console.log(d) // error
}
foo();
注意:
- var - 存储在 变量环境;
let
/const
- 存储在 词法环境; - 创建 执行上下文的时候,var 定义的变量就会声明为
undefined
- 当作用域块执行结束后,内部定义的变量就会从 词法环境 栈顶弹出
词法环境
const
和 let
进入的【词法环境】,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出。
查找变量的顺序
沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给JavaScript引擎,如果没有查找到,那么继续在变量环境中查找
案例1:
案例2: