编译原理

JavaScript的编译过程分为三个过程:词法分析语法分析代码生成

词法分析阶段主要是将代码分解成词法单元。语法分析是将这些词法单元流转换成一个有元素逐级嵌套所组成的代表了程序语法结构的树,抽象语法树AST。代码生成是将AST转换为可执行代码的过程。

作用域

作用域分为静态作用域动态作用域

静态作用域是在定义的时候就确定了变量的值,而动态作用域是在执行的时候才确定变量的值。

词法作用域就是定义在词法阶段的作用域。也就是说词法作用域是在写代码时将变量和块作用域在哪里决定,所以说一般情况下词法分析器处理代码时会保持词法作用域不变。

作用域又分为函数作用域块级作用域

函数作用域就是说与这个函数的全部变量都可以在整个函数的范围内使用及复用,包括它内部的嵌套作用域。函数的作用域是在定义的时候就确定的。

块级作用域是是一个用来对最小授权原则进行扩展的工具,将代码从在函数中隐藏信息扩展为在块中隐藏信息。最常见的两个花括号就是一个块作用域。

ES5实现块级作用域的方式有:evalwithtry/catch的catch分句闭包

ES6就是let和const,块级作用域的好处是:垃圾回收和let循环。

作用域链

作用域链的产生是因为作用域发生嵌套。它是当前环境与上层环境的一系列变量对象组成的,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。当查找变量的时候,会先从当前的上下文变量对象中查找,如果没有找到,就会从父级的上下文变量对象中查找,直到找到全局上下文中的变量即全局对象。这个由多个执行上下文的变量对象构成的链表叫做作用域链。

作用域链是在函数定义的时候就已经决定的。

这是因为函数有一个内部属性[[scope]],当函数创建的时候,就会保存所有父变量对象到其中,[[scope]]就是所有父变量对象的层级链,但是注意,[[scope]]并不代表一个函数完成的作用域链。[[scope]]是在函数创建阶段的,当函数执行后,会将函数本身的AO和[[scope]]合并,这才是这个函数完整的作用域链。

  1. ScopeChain = AO.concat([[scope]])

相关

作用域是 JavaScript中一个相当重要的概念,它与许多知识点都息息相关,也可以说由它衍生出的。比如说变量提升立即执行函数闭包ES5模块等相关知识点。