详解JavaScript的BUG和错误(5)

在很多情况下,当错误很常见并且调用者应该明确地考虑它们时,返回特殊值是表示错误的好方法。 但它确实有其不利之处。 首先,如果函数已经可能返回每一种可能的值呢? 在这样的函数中,你必须做一些事情,比如将结果包装在一个对象中,以便能够区分成功与失败。

function lastElement(array) {
 if (array.length == 0) {
 return {failed: true};
 } else {
 return {element: array[array.length - 1]};
 }
}

返回特殊值的第二个问题是它可能产生非常笨拙的代码。 如果一段代码调用promptNumber 10 次,则必须检查是否返回null 10 次。 如果它对null的回应是简单地返回null本身,函数的调用者将不得不去检查它,以此类推。

异常

当函数无法正常工作时,我们只希望停止当前任务,并立即跳转到负责处理问题的位置。这就是异常处理的功能。

异常是一种当代码执行中遇到问题时,可以触发(或抛出)异常的机制,异常只是一个普通的值。触发异常类似于从函数中强制返回:异常不只跳出到当前函数中,还会跳出函数调用方,直到当前执行流初次调用函数的位置。这种方式被称为“堆栈展开(Unwinding the Stack)”。你可能还记得我们在第3章中介绍的函数调用栈,异常会减小堆栈的尺寸,并丢弃所有在缩减程序栈尺寸过程中遇到的函数调用上下文。

如果异常总是会将堆栈尺寸缩减到栈底,那么异常也就毫无用处了。它只不过是换了一种方式来彻底破坏你的程序罢了。异常真正强大的地方在于你可以在堆栈上设置一个“障碍物”,当异常缩减堆栈到达这个位置时会被捕获。一旦发现异常,你可以使用它来解决问题,然后继续运行该程序。

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

function look() {
 if (promptDirection("Which way?") == "L") {
 return "a house";
 } else {
 return "two angry bears";
 }
}

try {
 console.log("You see", look());
} catch (error) {
 console.log("Something went wrong: " + error);
}

throw关键字用于引发异常。 异常的捕获通过将一段代码包装在一个try块中,后跟关键字catch来完成。 当try块中的代码引发异常时,将求值catch块,并将括号中的名称绑定到异常值。 在catch块结束之后,或者try块结束并且没有问题时,程序在整个try / catch语句的下面继续执行。

在本例中,我们使用Error构造器来创建异常值。这是一个标准的 JavaScript 构造器,用于创建一个对象,包含message属性。在多数 JavaScript 环境中,构造器实例也会收集异常创建时的调用栈信息,即堆栈跟踪信息(Stack Trace)。该信息存储在stack属性中,对于调用问题有很大的帮助,我们可以从堆栈跟踪信息中得知问题发生的精确位置,即问题具体出现在哪个函数中,以及执行失败为止调用的其他函数链。

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

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