什么是作用域
编译原理
分词 / 词法分析
这个过程会将由字符组成的字符串分解成 (对编程语言来说) 有意义的代码块, 这些代 码块被称为词法单元(token)
解析 / 语法分析
这个过程是将词法单元流 (数组) 转换成一个由元素逐级嵌套所组成的代表了程序语法 结构的树. 这个树被称为 "抽象语法树"(Abstract Syntax Tree,AST).
什么是抽象树呢? 在这个网站上可以在线的看到 JS 源代码, 也就是抽象树 在线生成抽象树 https://esprima.org/demo/parse.html#
代码生成
将 AST 转换为可执行代码的过程被称为代码生成.
对于 JavaScript 来说, 大部分情况下编译发生在代码执行前的几微秒 (甚至更短!) 的时间内.
任何 JavaScript 代码片段在执行前都要进行编译(通常就在执行前).
因此, JavaScript 编译器首先会对 var a = 2; 这段程序进行编译, 然后做好执行它的准备, 并且通常马上就会执行它.
理解作用域
引擎
从头到尾负责整个 JavaScript 程序的编译及执行过程.
编译器
引擎的好朋友之一, 负责语法分析及代码生成等脏活累活
作用域
引擎的另一位好朋友, 负责收集并维护由所有声明的标识符 (变量) 组成的一系列查 询, 并实施一套非常严格的规则, 确定当前执行的代码对这些标识符的访问权限.
编译器负责代码生成, 在生成的过程中会询问作用域, 例如变量是否声明了. 引擎整个编译执行过程中也会询问作用域
其中有 LHS 查询和 RHS 查询
对话(加强理解版)
- function foo(a) {
- console.log( a ); // 2
- }
- foo( 2 );
引擎: 我说作用域, 我需要为 foo 进行 RHS 引用. 你见过它吗?
作用域: 别说, 我还真见过, 编译器那小子刚刚声明了它. 它是一个函数, 给你.
引擎: 哥们太够意思了! 好吧, 我来执行一下 foo.
引擎: 作用域, 还有个事儿. 我需要为 a 进行 LHS 引用, 这个你见过吗?
作用域: 这个也见过, 编译器最近把它声名为 foo 的一个形式参数了, 拿去吧.
引擎: 大恩不言谢, 你总是这么棒. 现在我要把 2 赋值给 a.
引擎: 哥们, 不好意思又来打扰你. 我要为 console 进行 RHS 引用, 你见过它吗?
作用域: 咱俩谁跟谁啊, 再说我就是干这个. 这个我也有, console 是个内置对象.
给你.
引擎: 么么哒. 我得看看这里面是不是有 log(..). 太好了, 找到了, 是一个函数.
引擎: 哥们, 能帮我再找一下对 a 的 RHS 引用吗? 虽然我记得它, 但想再确认一次.
作用域: 放心吧, 这个变量没有变动过, 拿走, 不谢.
引擎: 真棒. 我来把 a 的值, 也就是 2, 传递进 log(..).
听我的, 多看几遍就能理解作用域跟 LHS 查询 RHS 查询
作用域链
这是前端面试中经常会被问到的问题, 这次我会想换一种方式回答这个问题.
作用域就好比是一栋大楼其中的一层, 如果引擎询问作用域查找某一个变量, 他会先询问 (LHS 和 RHS) 当前作用域,
如果当前作用域没有就会往上询问父级作用域, 以此类推, 直到最顶层(全局作用域), 无论有没有找到都会停止查找
fannie 总结
来源: https://www.cnblogs.com/ifannie/p/11428826.html