第一章 作用域是什么

时间:2021-10-28 14:49:24

1.1 编译原理

传统编译步骤

分词/词法分析(拆分成一个个词法单元)——>解析/语法分析(词法单元流转化为抽象语法树)——>代码生成(将抽象语法书(AST)转化为可执行代码(机器指令))

js引擎比上述要复杂,在各个阶段会有特定步骤来对性能进行优化,比如冗余元素。

其他很多语言的编译多发生在构建之前,而js大部分情况下的编译是发生在代码执行前的短短几微秒内,没有其他语言编译器那样有那么多的时间进行优化,所以js引擎想了各种办法来保证性能最佳(比如JIT,可以延迟编译甚至实施重编译)。

1.2 理解作用域

以var a = 2为例,执行这个语句需要引擎,编译器,作用域的配合。

第一章 作用域是什么

编译器查询方式

以LHS和RHS为例,LHS查询是视图找到变量的容器本身,并对去赋值,而RHS是简单的查找某个变量的值。

比如console.log(a),这里对a的引用就是RHS,并没有进行任何赋值。

而a=2,这里对a的引用就是LHS,并不关心当前的值是什么,只是要为 '=2' 这个赋值操作找到一个目标。

注:eg:foo(a)中实际上含有一个隐式 'a=2' 操作,不要忽略这一个LHS查询。

注:函数声明function foo(a) {...}不能简单的理解为LHS查询和赋值操作(var foo,foo = function(a){...}),因为编译器可以在代码生成的同时处理声明和值的定义。

1.4 异常

在变量还没有声明的情况下,这两种查询的行为是不同的。RHS如果找不到该变量,引擎会抛出ReferenceError的错误,而LHS则会在全局作用域下创建一个具有该名称的变量,并将其返还给引擎(需要程序运行在非'严格模式'下,'严格模式'下,引擎会抛出同RHS类似的ReferenceError异常)。