详解JavaScript的BUG和错误(8)

我们不如定义一个新的错误类型,并使用instanceof来识别异常。

class InputError extends Error {}

function promptDirection(question) {
 let result = prompt(question);
 if (result.toLowerCase() == "left") return "L";
 if (result.toLowerCase() == "right") return "R";
 throw new InputError("Invalid direction: " + result);
}

新的错误类扩展了Error。 它没有定义它自己的构造器,这意味着它继承了Error构造器,它需要一个字符串消息作为参数。 事实上,它根本没有定义任何东西 - 这个类是空的。 InputError对象的行为与Error对象相似,只是它们的类不同,我们可以通过类来识别它们。

现在循环可以更仔细地捕捉它们。

for (;;) {
 try {
 let dir = promptDirection("Where?");
 console.log("You chose ", dir);
 break;
 } catch (e) {
 if (e instanceof InputError) {
  console.log("Not a valid direction. Try again.");
 } else {
  throw e;
 }
 }
}

这里的catch代码只会捕获InputError类型的异常,而其他类型的异常则不会在这里进行处理。如果又输入了不正确的值,那么系统会向用户准确报告错误——“绑定未定义”。

断言

断言(assertions)是程序内部的检查,用于验证某个东西是它应该是的方式。 它们并不是用于处理正常操作中可能出现的情况,而是发现程序员的错误。

例如,如果firstElement被描述为一个函数,永远不会在空数组上调用,我们可以这样写:

function firstElement(array) {
 if (array.length == 0) {
 throw new Error("firstElement called with []");
 }
 return array[0];
}

现在,它不会默默地返回未定义值(当你读取一个不存在的数组属性的时候),而是在你滥用它时立即干掉你的程序。 这使得这种错误不太可能被忽视,并且当它们发生时更容易找到它们的原因。

我不建议尝试为每种可能的不良输入编写断言。 这将是很多工作,并会产生非常杂乱的代码。 你会希望为很容易犯(或者你发现自己做过)的错误保留他们。

本章小结

错误和无效的输入十分常见。编程的一个重要部分是发现,诊断和修复错误。 如果你拥有自动化测试套件或向程序添加断言,则问题会变得更容易被注意。

我们常常需要使用优雅的方式来处理程序可控范围外的问题。如果问题可以就地解决,那么返回一个特殊的值来跟踪错误就是一个不错的解决方案。或者,异常也可能是可行的。

抛出异常会引发堆栈展开,直到遇到下一个封闭的try/catch块,或堆栈底部为止。catch块捕获异常后,会将异常值赋予catch块,catch块中应该验证异常是否是实际希望处理的异常,然后进行处理。为了有助于解决由于异常引起的不可预测的执行流,可以使用finally块来确保执行try块之后的代码。

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

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