异常
当函数无法正常工作时,我们只希望停止当前任务,并立即跳转到负责处理问题的位置。这就是异常处理的功能。
异常是一种当代码执行中遇到问题时,可以触发(或抛出)异常的机制,异常只是一个普通的值。触发异常类似于从函数中强制返回:异常不只跳出到当前函数中,还会跳出函数调用方,直到当前执行流初次调用函数的位置。这种方式被称为“堆栈展开(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
属性中,对于调用问题有很大的帮助,我们可以从堆栈跟踪信息中得知问题发生的精确位置,即问题具体出现在哪个函数中,以及执行失败为止调用的其他函数链。
需要注意的是现在look
函数可以完全忽略promptDirection
出错的可能性。这就是使用异常的优势:只有在错误触发且必须处理的位置才需要错误处理代码。其间的函数可以忽略异常处理。
嗯,我们要讲解的理论知识差不多就这些了。