在 JavaScript 中,空语句返回的是空值(empty),而 throw 语句则返回 throw 类型的结果,该返回结果(Result)在 ECMAScript 中称为完成记录(Completion)。
语句有五种完成状态(normal, break, continue, return, 以及 throw)。Nomal(缺省状态)大多数情况下是不被读取的;break 和 continue 用于循环和标签化语句,不携带返回值;return 则是用于函数的返回值;throw(异常抛出)不拦截捕获会终止程序运行。其中 return 和 throw 两个状态是确保返回时携带有效值(包括 undefined)的;其他的完成类型则可能在返回时携带空值(empty)。
而语句块中的多个语句顺序执行时,后执行语句的返回值,会覆盖之前执行的语句的返回值。其覆盖遵从以下两条规则:
1. 在向前覆盖既有的语句完成值时,empty值不覆盖任何值(即一个语句块会尽量将块中最后有效的值返回出来);
2. 部分语句在没有有效返回值,且既有语句的返回值是empty时,默认用undefined覆盖之(在 ECMAScript 6 之后,if、do…while、while、for / for…in / for…of、with、switch 和 try 语句块中不会返回 empty,其执行结果至少会返回一个 undefined 值)。
因此当一个语句块的最终语句是 break 或 continue 以及其他一些不携带返回值的语句时,其也有可能会返回有效值。
JavaScript 引擎能够区分执行的是语句还是表达式,执行语句返回完成记录,执行表达式返回引用记录。
当外层的处理逻辑发现是一个引用时,会再根据当前逻辑的需要将该引用理解为左操作数(取引用)或右操作数(取值);否则当它是一个完成记录,尝试检测它的类型,也就是语句的完成状态。
而在执行一个语句时,如果是 normal,则继续处理;否则将该完成状态原样返回,交由外部的、其他的代码来处理。。循环语句和标签语句将处理 break 和 continue ,将其替换为 normal;函数的内部过程将处理 return,也会将其替换为 normal;而 try 语句将处理 throw,在 catch 块中替换成 normal,以表示 try 语句正常完成;或在 finally 中不做任何处理,继续维持既有的完成状态,也就是 throw。所以语句最终的完成状态会是 normal 或 throw。
----- 极客时间《JavaScript 核心原理解析》学习笔记 Day 11 -----