part1
作用域和闭包
尽管通常将Javascript归类为动态或解释执行语言,但事实上它是一门编译语言。
在传统编译语言的流程中,程序中的一段源代码在执行之前会经历三个步骤:
①分词/词法分析
这个过程会将由字符组成的字符串分解成(对编程语言来说)有意义的代码块,这些代码块被称为词法单元(token)
②解析/语法分析
这个过程是将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。
③代码生成
将 AST 转换为可执行代码的过程称被称为代码生成。这个过程与语言、目标平台等息息相关。
比起那些编译过程只有三个步骤的语言的编译器,JavaScript 引擎要复杂得多
作用域:
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。如果查找的目的是对变量进行赋值,那么就会使用 LHS 查询;如果目的是获取变量的值,就会使用 RHS 查询。
(变量的赋值操作会执行两个动作,首先编译器会在当前作用域中声明一个变量(如果之前没有声明过),然后在运行时引擎会在作用域中查找该变量,如果能够找到就会对它赋值。)
查找的类型分为 LHS 查询、 RHS查询
当变量出现在赋值操作的左侧时进行 LHS 查询,出现在右侧时进行 RHS 查询(RHS 查询与简单地查找某个变量的值别无二致,而 LHS 查询则是试图找到变量的容器本身,从而可以对其赋值)
LHS 和 RHS 查询都会在当前执行作用域中开始,当引擎执行 LHS 查询时,如果在顶层(全局作用域)中也无法找到目标变量,全局作用域中就会创建一个具有该名称的变量,并将其返还给引擎,前提是程序运行在非“严格模式”下
如果 RHS 查询在所有嵌套的作用域中遍寻不到所需的变量,引擎就会抛出 ReferenceError异常。
而 TypeError 则代表作用域判别成功了,但是对结果的操作是非法或不合理的。
词法作用域
作用域共有两种主要的工作模型。第一种是词法作用域(最为普遍的,被大多数编程语言所采用的)。另外一种叫作动态作用域。
词法作用域就是定义在词法阶段的作用域。只由函数被声明时所处的位置决定。
欺骗词法作用域会导致性能下降。
eval(..) 函数如果接受了含有一个或多个声明的代码,就会修改其所处的词法作用域,而with 声明实际上是根据你传递给它的对象凭空创建了一个全新的词法作用域。