scope
作用域
作用域决定了一段代码能访问到那些数据,这些数据保存在词法环境对象中
变量与函数的作用范围,控制着变量与函数的可见性与声明周期
es6 之前只有全局作用域与函数作用域。
块级作用域
为了解决变量提升带来的覆盖与污染问题,出现了块级作用域 const、let
1 |
|
1.函数内部通过 var 声明的变量,在编译阶段全都被存放到变量环境里面了。
2.通过 let 声明的变量,在编译阶段会被存放到词法环境(Lexical Environment)中。
3.在函数的作用域块内部,通过 let 声明的变量并没有被存放到词法环境中
执行这个作用域块的时候,作用域块中通过 let 声明的变量,会被存放在词法环境的一个单独的区域中
其实,在词法环境内部,维护了一个小型栈结构,栈底是函数最外层的变量,进入一个作用域块后,就会把该作用域块内部的变量压到栈顶;当作用域执行完成之后,该作用域的信息就会从栈顶弹出,这就是词法环境的结构。需要注意下,我这里所讲的变量是指通过 let 或者 const 声明的变量
当执行到作用域块中的console.log(a)这行代码时,就需要在词法环境和变量环境中查找变量 a 的值了,具体查找方式是:沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给 JavaScript 引擎,如果没有查找到,那么继续在变量环境中查找。
变量提升与块级作用域的提升
变量环境实现函数级作用域:
执行一个函数时,会创建一个执行上下文,其中的变量环境会保存该函数代码内生成的变量
块级作用域通过词法环境的栈结构实现
执行时机
函数只会在第一次执行的时候被编译,所以编译时变量环境和词法环境最顶层数据已经确定了。
当执行到块级作用域的时候,块级作用域中通过let和const申明的变量会被追加到词法环境中,当这个块执行结束之后,追加到词法作用域的内容又会销毁掉。
参考:
https://www.jianshu.com/p/0fcc26e13300
思考
1.函数级作用域如何实现?
2.块级作用域又是如何实现的?
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!