08 JS如何实现块级作用域

Posted by CodingWithAlice on April 10, 2021

08 JS如何实现块级作用域

总结

块级作用域就是通过 词法环境 的栈结构来实现的,而变量提升是通过变量环境来实现

块级作用域

作用域:指在程序中定义变量的区域,该位置决定了变量的生命周期。

变量提升的缺陷:

  • 变量容易在不被察觉的情况下被覆盖掉
  • 本应销毁的变量没有被销毁

ES6通过引入块级作用域并配合 letconst 关键字解决 变量提升 的问题,作用块内声明的变量不影响块外面的变量。

块级作用域的实现

从执行上下文角度看块级作用域的实现(以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
  • 当作用域块执行结束后,内部定义的变量就会从 词法环境 栈顶弹出

image-20210410195713644

词法环境

constlet 进入的【词法环境】,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出。

查找变量的顺序

沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给JavaScript引擎,如果没有查找到,那么继续在变量环境中查找

案例1:

image-20210410195802828

案例2:

image-20210411105239990