道招

《浏览器工作原理与实践》笔记之JavaScript是如何支持块级作用域的

如果您发现本文排版有问题,可以先点击下面的链接切换至老版进行查看!!!

《浏览器工作原理与实践》笔记之JavaScript是如何支持块级作用域的

你已经知道 JavaScript 引擎是通过变量环境实现函数级作用域的,那么 ES6 又是如何在函数级作用域的基础之上,实现对块级作用域的支持呢?


function foo(){
    var a = 1
    let b = 2
    {
      let b = 3
      var c = 4
      let d = 5
      console.log(a)
      console.log(b)
    }
    console.log(b) 
    console.log(c)
    console.log(d)
}   
foo()

执行流程如下

  • 编译并创建执行上下文

1.函数内部通过 var 声明的变量,在编译阶段全都被存放到变量环境里面了。 2.通过 let 声明的变量,在编译阶段会被存放到词法环境(Lexical Environment)中。 3.在函数的作用域块内部,通过 let 声明的变量并没有被存放到词法环境中。

  • 续执行代码

从图中看出,当进入函数的作用域块时,作用域块中通过 let 声明的变量,会被存放在词法环境的一个单独的区域中,这个区域中的变量并不影响作用域块外面的变量,比如在作用域外面声明了变量 b,在该作用域块内部也声明了变量 b,当执行到作用域内部时,它们都是独立的存在。

其实,在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。需要注意下,我这里所讲的变量是指通过 let 或者 const 声明的变量。

再接下来,当执行到作用域块中的console.log(a)这行代码时,就需要在词法环境和变量环境中查找变量 a 的值了,具体查找方式是:沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给 JavaScript 引擎,如果没有查找到,那么继续在变量环境中查找。

变量查找过程就完成了,你可以参考下图:

当作用域块执行结束之后,其内部定义的变量就会从词法环境的栈顶弹出,最终执行上下文如下图所示:

块级作用域就是通过词法环境的栈结构来实现的,而变量提升是通过变量环境来实现,通过这两者的结合,JavaScript 引擎也就同时支持了变量提升和块级作用域了。

本文截取自《浏览器工作原理与实践》09 | 块级作用域:var缺陷以及为什么要引入let和const?

更新时间:
上一篇:《浏览器工作原理与实践》笔记之CSS、JS阻塞DOM合成场景分析下一篇:《浏览器工作原理与实践》笔记之从堆栈空间看闭包过程

相关文章

关注道招网公众帐号
道招开发者二群