优秀的编程知识分享平台

网站首页 > 技术文章 正文

《你不知道的JavaScript(上卷)》第一章 作用域是什么 「笔记」

nanyue 2024-07-22 14:10:19 技术文章 8 ℃

三个概念

引擎:从头到尾负责整个JavaScript程序的编译及执行过程


编译器(负责语法分析和代码生成等):

第一步:分词/词法分析。将由字符组成的字符串分解成有意义的代码块,这些代码块被称为词法单元。

第二步:解析/语法分析。将词法单元流(数组)转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。这个树被称为“抽象语法树”(AST)。

第三步:代码生成。将AST转换为可执行代码的过程。


作用域:负责收集并维护由所有声明的标识符(变量)组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。


编译器查询变量的两种方式:LHS和RHS

“L”和“R”表示左和右,是一个赋值操作的左侧和右侧。

例如:let a = b

首先对b进行RHS,找到b,拿到它的值,然后就停止。再找到a,给他进行赋值操作,并不关心它之前的值。

准确来说,RHS并不是真正意义上的“赋值操作的右侧”,而是“非左侧”,例如:console.log(a),需要使用RHS查询到拿到a的值,但是连个等号都没有。


作用域嵌套

当一个块或函数嵌套在另一个块或函数中时,就发生了作用域的嵌套。因此,当在此前作用域中无法找到某个变量时,引擎就会在外层嵌套的作用域中继续查找,直到找到该变量,或抵达最外层的作用域(即全局作用域)为止。

考察如下代码:

function foo(a){
	console.log(a + b)
}
var b = 2
foo(2)    // 4

foo函数内部找不到b变量时,就会向上一级作用域查找(该例中就是全局作用域),找到就停止,找不到就报错。


引擎抛出的两种异常

对RHS来说,如果找到全局作用域还是没找到,就会抛出ReferenceError异常。如果找到了,但是试图对该变量进行不合理的操作,例如对一个非函数类型的变量进行函数调用,或者引用null或undefined类型的值中的属性,那么会抛出TypeError异常

对LHS来说,如果在“非严格模式”下,需要被赋值的变量找不到,就会在全局创建一个具有该名称的变量,不会报错。而在“严格模式”下,会抛出同RHS查询失败时类似的ReferenceError异常。

总结:ReferenceError同作用域判别失败相关,而TypeError则代表作用域判别成功了,但是对结构的操作是非法的或不合理的。

最近发表
标签列表