本文会用思惟导图的形式列出本书该部分的知识点(剔除案例),构建知识脉络。因为是导读,正文部分只会列举部分的内容。本文适合未读过此书的同窗参考,另外读过此书的同窗,若是能纯熟得答出文初的问题,那么相信您对于这部分的内容能够说是记忆深入了。编程
建议在阅读前了解做者的平生,背景,核心贡献及思想。相信会对理解本书以及后续的选书读书会有所帮助。bash
豆瓣读书编程语言
ReferenceError
异常类型 和 TypeError
异常类型。谈谈你对做用域的理解。(我的理解,求拍砖)函数
做用域收集而且维护由全部声明的标识符组成的查询,有本身很是严格的规则肯定当前执行代码对标识符的访问权限。性能
JavaScript 是一门编译语言,在执行代码前的编译中,编译器须要和做用域沟通是否存在某个变量来决定建立仍是忽略。优化
接着引擎须要为变量赋值,它会经过 LHS查询
或者 RHS查询
查找变量,在当前做用域找不到时还要沿着做用域链一直往上往上找,若是在最外层的全局做用域也找不到,那么抛出叫作 ReferenceError 的异常spa
这里若是是使用 LHS查询
当全局做用域也不存在查找的变量时会自动建立并返还给引擎。code
JavaScript
是一门编译语言,可是它不像传统语言那样仅仅只经历编译的三个步骤,分词/词法分析,解析/语法分析,代码生成。cdn
咱们的 JavaScript
引擎要复杂的多,JavaScript
会用尽各办法(好比用JIT
)来保证性能最佳。而且咱们要记住的是任何 JavaScript
代码片断在执行前都要进行编译,大部分状况下编译发生在代码执行前的几微秒(甚至更短)。对象
分词/词法分析:这个过程会将字符串分解成对编程语言来讲有意义的词法单元(代码块)
var a = zhengyang;
复制代码
以上代码会被分解成 var、a、=、; 空格是否会被当成语法单元取决于它是否在此处具备意义。
分词和词法分析实际上是一件事,词在这里指的是带有某种归类的字符串,词经过词法来划分,分词是目的,词法分析是手段。
解析/语法分析:这个过程会将词法单元流转化成一个由元素逐级嵌套所组成的表明程序语法结构的树,这个树叫作抽象语法树(Abstract Syntax Tree
,AST)。
var a = zhengyang;
复制代码
通过分词/词法分析,咱们把划分好的代码块组成抽象语法树,它有一个 VariableDeclaration
(变量声明) 的顶级节点,下面是一个 Identitier
(值为a)的子节点和一个叫作 AssignmentExpression
(赋值表达式)的子节点,AssignmentExpression
有一个叫作 NumericLiteral
(数值文字)的值为 2 的子节点。
代码生成:将 AST
转化为课执行代码的过程被称为代码生成。
简单来讲就是将 var a = 2
的 AST
转化为一组机器指令来创造一个叫作 a 的变量,并将一个值存储在 a 中。
引擎:从头至尾负责整个 JavaScript
的编译及执行过程。
编译器:引擎的同事负责语法分析及代码生成等脏活累活。
做用域:引擎的另外一位同事,负责收集而且维护全部声明的标识符组成的一些列咨询。它由一套很是严格个规则,肯定当前执行的代码对这些标识符的访问权限。
三位一体工做流:
var a = zhengyang
复制代码
var a
,编译器会咨询做用域是否已经存在该名称的变量存在于同一个做用域集合中。是,就忽略 var a
继续编译;不然就会要求在当前做用域集合中生命一个新的变量,命名为 aa = 2
这个赋值操做。引擎在运行时会先咨询做用域,当前的做用域集合中是否存在一个叫作a的变量。是,就会使用这个变量;否,引擎就会继续查找该变量。LHS查询
与 RHS查询
:简单来讲 LHS
查询就是当变量出如今赋值操做的左侧时进行的查询, RHS查询
就是变量出如今赋值操做的右侧时进行的查询。要注意,查找只会在当前做用域进行。console.log(a)
复制代码
以上代码就是 RHS查询
,咱们能够看到变量 a 出如今右侧。
a = 2
复制代码
以上代码就是 LHS查询
, 变量 a 出如今左侧。 6. 看一个具体例子
function foo(a) {
console.log(a);//2
}
foo (2)
复制代码
以上代码首先进行的声明 foo 函数,变量在右因此使 RHS查询
而后是隐式的 a = 2
这里采用 RHS查询
,变量在左因此使用 LHS查询
console.log
console是内置对象,找 log
变量在右使用 RHS查询
console.log(a)
同上变量在右使用 RHS查询
做用域是根据名称查找变脸的一套规则,当一个块或函数嵌套在另外一个块或函数中时就发生了做用域的嵌套。在当前做用域没法找到某个变量时,引擎就会在外层嵌套的做用域中继续查找,直到找到该变量为止。
function foo(a){
console.log(a + b)
}
var b = 2
foo(2); //4
复制代码
上面的代码中 console.log(a + b)
咱们在函数做用域中找不到 b 只能在上层的全局做用域中找
遍历嵌套做用域做用域链的规则:引擎从当前的执行做用于开始查找变量,若是找不到就去上级继续查找。当抵达最外层的全局做用域时,若是尚未找到,那么查找就会中止。
function foo(a) {
console.log( a + b);
b = a;
}
复制代码
以上代码会报 ReferenceError
的异常,由于咱们经过 RHS 查询
在全部的嵌套做用域中都找不到 b。
相比之下若是是用 LHS查询
非严格模式下,若是在全局做用于中也找不到就会帮你建立一个具备该名称的变量,而且返还给引擎。
严格模式禁止自动或隐式地建立全局变量。所以在严格模式中 LHS查询
失败时并不会建立并返回一个全局变量,而是会抛出 ReferenceError
异常。
TypeError
若是经过 RHS查询
找到了一个变量,可是你尝试对这个变量的值进行不合理的操做,好比对一个非函数类型进行函数调用那么就会抛出 TypeError
异常。
var a = 'zhengyang'
复制代码
a = 'zhengyang'
这个赋值操做。LHS查询
或者 RHS查询
在当前做用域查找变量。若是找到了引擎就会使用这个变量将 'zhengyang' 这个值赋给它。ReferenceError
异常。LHS查询
,当最外层的全局做用域也不存在要查找的变量时会自动建立而且返回该变量给引擎,严格模式下则不可,由于严格模式禁止自动或隐式建立全局变量。