详解JavaScript的BUG和错误(7)

选择性捕获

当程序出现异常且异常未被捕获时,异常就会直接回退到栈顶,并由 JavaScript 环境来处理。其处理方式会根据环境的不同而不同。在浏览器中,错误描述通常会写入 JavaScript 控制台中(可以使用浏览器工具或开发者菜单来访问控制台)。我们将在第 20 章中讨论的,无浏览器的 JavaScript 环境 Node.js 对数据损坏更加谨慎。 当发生未处理的异常时,它会中止整个过程。

对于程序员的错误,让错误通行通常是最好的。 未处理的异常是表示糟糕的程序的合理方式,而在现代浏览器上,JavaScript 控制台为你提供了一些信息,有关在发生问题时堆栈上调用了哪些函数的。

对于在日常使用中发生的预期问题,因未处理的异常而崩溃是一种糟糕的策略。

语言的非法使用方式,比如引用一个不存在的绑定,在null中查询属性,或调用的对象不是函数最终都会引发异常。你可以像自己的异常一样捕获这些异常。

进入catch语句块时,我们只知道try体中引发了异常,但不知道引发了哪一类或哪一个异常。

JavaScript(很明显的疏漏)并未对选择性捕获异常提供良好的支持,要不捕获所有异常,要不什么都不捕获。这让你很容易假设,你得到的异常就是你在写catch时所考虑的异常。

但它也可能不是。 可能会违反其他假设,或者你可能引入了导致异常的 bug。 这是一个例子,它尝试持续调用promptDirection,直到它得到一个有效的答案:

for (;;) {
 try {
 let dir = promtDirection("Where?"); // ← typo!
 console.log("You chose ", dir);
 break;
 } catch (e) {
 console.log("Not a valid direction. Try again.");
 }
}

我们可以使用for (;;)循环体来创建一个无限循环,其自身永远不会停止运行。我们在用户给出有效的方向之后会跳出循环。但我们拼写错了promptDirection,因此会引发一个“未定义值”错误。由于catch块完全忽略了异常值,假定其知道问题所在,错将绑定错误信息当成错误输入。这样不仅会引发无限循环,而且会掩盖掉真正的错误消息——绑定名拼写错误。

一般而言,只有将抛出的异常重定位到其他地方进行处理时,我们才会捕获所有异常。比如说通过网络传输通知其他系统当前应用程序的崩溃信息。即便如此,我们也要注意编写的代码是否会将错误信息掩盖起来。

因此,我们转而会去捕获那些特殊类型的异常。我们可以在catch代码块中判断捕获到的异常是否就是我们期望处理的异常,如果不是则将其重新抛出。那么我们该如何辨别抛出异常的类型呢?

我们可以将它的message属性与我们所期望的错误信息进行比较。 但是,这是一种不稳定的编写代码的方式 - 我们将使用供人类使用的信息来做出程序化决策。 只要有人更改(或翻译)该消息,代码就会停止工作。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/416.html