预编译(预解析)
- 执行上下文:js代码运行时所处的环境,分为全局上下文和函数上下文。 - 全局上下文(全局环境):打开浏览器就自动创建的,在浏览器中,全局上下文就是window对象。 - 函数上下文(函数内部环境),在函数被调用的时候创建的 在上下文创建以后,会先进行预编译的过程,根据上下文不同,预编译分为全局预编译和函数预编译。 每个执行上下文都有一个与之相关联的变量对象(Variable Object),当前执行上下文中所有的变量和函数都添加在其中。
全局预编译(解析)流程
var和function提升到当前作用域的最前面。
- 将变量声明的变量名作为VO对象的属性名,属性值置为undefined;
- 将函数声明的函数名作为VO对象的属性名,属性值为函数本身;
- 函数名与变量名冲突,函数声明会覆盖变量声明,属性值为函数本身
- 预编译结束,逐行执行代码
函数预编译
函数执行上下文是在函数调用的时候创建的 全局的VO(变量对象)在函数预编译阶段被叫做AO(活动对象)。 流程:
- 将变量声明的变量名作为AO对象的属性名,属性值为undefined;
- 将形参名作为AO对象的属性名,属性值为undefined;
- 形参名和变量名冲突时,形参会覆盖变量声明
- 将实参的值赋予形参,替换AO对象中形参的属性值
- 将函数名作为AO对象的属性名,属性值为函数本身
- 函数名与变量名冲突,函数声明会覆盖变量声明 函数>实参>变量
编译原理
分词/词法分析
将由字符组成的字符串分解成对编程语言来说有意义的代码块,这些代码块被称为词法单元。空格是否会被当作词法单元,取决于空格在这门语言中是否具有意义。分词和词法分析之间的区别主要差异在于词法单元的识别是通过有状态还是无状态的方法进行的。如果词法单元生成器在判断a是独立的词法单元还是其他词法单元的一部分时,调用的是有状态的解析规则,这个过程被称为词法分析。
解析/语法分析
将词法单元流(数组)转换为一个由元素逐级嵌套组成的代表了程序语法结构的树(AST)。
代码生成
将AST转换为可执行代码的过程被称为代码生成。
参考资料
- 你不知道的JavaScript(上卷) 凯尔辛普森
- JS基础篇:6、JS执行上下文与预编译(预解析) - 掘金 (juejin.cn)