《JavaScript 权威指南》解读——try/catch/finally
try/catch/finally 语句用于异常处理,catch 和 finally 都不是必需的,但至少存在一个。
try 块中发生异常时,当即进入 catch 块执行,这称为异常被捕获。
try 块中的异常可以源自两处:
- 直接的 throw 语句
- 被调用的函数中的异常,因为未捕获的异常沿调用栈向上级传递(或称冒泡)
catch 块接收 throw 的异常值作为参数,通常是 Error 对象。
catch 块有两个效用:
- 对异常进行逻辑响应
- 异常进入 catch 块表示被捕获,将停止冒泡
catch 块往往需要判别异常对象的特征,获取异常信息。对无法接受的异常可用 throw 再次抛出,让其继续冒泡。
catch 块不关心异常值,只用于阻止冒泡时,异常形参可省略(ES2019)。
finally 块用于给 try 块扫尾。如果执行进入了 try 块,则无论 try 块的执行如何告终,其伴侣 finally 块都会被执行,且 finally 块的执行要么紧随 try 块,要么紧随 catch 块。try 块可能的结束方式有:
- 正常结束,碰到块末尾
- break, continue, return 语句导致
- 遇到了可被伴侣 catch 块捕获的异常
- 遇到了未捕获的异常,该异常仍在向上级冒泡
只有上述第三种情况 finally 块紧随 catch 块执行,其它情况下紧随 try 块。
可以说 finally 在跳转流程中插了一脚,使跳转处于挂起状态。需要注意的是,finally 中的主动跳转有最终话语权:如果 finally 块中使用了 return, continue, break 语句,或者直接间接地抛出了异常,这些行为导致的跳转将取代被 finally 挂起的跳转,即让挂起的跳转消失。从这个意义上看,finally 块也可以消化异常,即停止其继续冒泡。