try-catch 语句在 JavaScript 中用于处理运行时错误(异常)。这是大多数编程语言中常用的处理异常的方式。try-catch 语句只能处理运行时错误。try 块必须跟随一个 catch 块或者一个 finally 块(或者两者都有)。
在 try{} 语句内,你可以编写有错误或有可能产生错误的代码。你也可以把常规的 JavaScript 代码写入 try{} 语句内。
catch{} 语句用来处理错误。当 try{} 语句中的代码出现任何错误时,JavaScript 引擎会执行 catch{} 语句中的代码来处理这些错误。
如果 try{} 语句中的代码没有发生错误,它就会跳过 catch{} 语句中的代码,并执行后续的代码。
语法
你可以遵循下面的语法在代码中使用 try-catch 语句来处理异常。
try {
} catch(error) {
}
你可以在 catch{} 语句中打印错误对象或基于错误类型自定义错误信息来显示错误。
参数
-
error
− catch{} 语句接受‘error’对象作为参数。它包含 name 和 message 属性。然而,这是一个可选参数。
示例
在下面的代码中,我们在 try{} 语句内给 ‘num’ 变量赋 ‘num1’ 变量的值。这里,‘num1’ 变量未定义。所以,它会抛出一个错误。
在 catch{} 语句中,我们打印错误对象的 ‘name’ 和 ‘message’ 属性的值。
在输出中,你可以观察到它抛出了一个带有适当错误信息的引用错误。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
let num = num1;
} catch (err) {
output.innerHTML += "The error name is: " + err.name + "<br>";
output.innerHTML += "The error message is: " + err.message + ".<br>";
}
</script>
</body>
</html>
输出
The error name is: ReferenceError
The error message is: num1 is not defined.
当 try{} 语句中的任何错误发生时,它会跳过剩余代码的执行并执行 catch{} 语句中的代码。
让我们通过下面的例子来理解它。
示例
在下面的代码中,我们调用了一个未定义的 welcome() 函数。因此,它会抛出一个引用错误。
在 catch{} 语句中,我们处理了这个错误。
在输出中,你可以看到它打印了 try{} 语句的开始信息,catch{} 语句的开始信息,以及错误信息。由于错误发生在结束信息之前,因此它跳过了 try{} 语句的结束信息。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
output.innerHTML += "In the start of try block <br>";
welcome();
output.innerHTML += "In the end of try block <br>";
} catch (err) {
output.innerHTML += "In the catch block <br>";
output.innerHTML += "The error name is: " + err.name + "<br>";
output.innerHTML += "The error message is: " + err.message + ".<br>";
}
</script>
</body>
</html>
输出
In the start of try block
In the catch block
The error name is: ReferenceError
The error message is: welcomeis not defined.
注意 − try-catch 语句不允许你处理语法错误。它只能处理运行时错误。
例如,如果你运行下面的代码。它会在浏览器的控制台中显示出错,但是无法用 {} 语句捕捉到这个错误。
try {
let num = ;
} catch (err) {
}
JavaScript try…catch…finally 语句
finally{} 语句允许你在完成了 try{} 和 catch{} 语句的执行后执行特定的代码。
无论 try{} 语句中是否发生了错误,JavaScript 总是执行 finally{} 语句中的代码。如果发生了错误,它先执行 catch{} 语句中的代码,然后执行 finally{} 语句中的代码。
示例
在下面的代码中,我们在 try{} 语句内部给变量 'a' 赋变量 'b' 的值。它会抛出一个错误。
在 catch{} 语句中,我们打印错误。
在 finally{} 语句中,它打印一条信息。
你可以从输出中观察到,它首先运行了 try{} 语句中的代码,接着是 catch{} 语句中的代码,最后是 finally{} 语句中的代码。
<html>
<body>
<div id = "output"> </div>
<script>
try {
let a = b;
} catch (e) {
document.getElementById("output").innerHTML = e;
}
finally {
document.getElementById("output").innerHTML += "<br>Finally block always executes";
}
</script>
</body>
</html>
输出
ReferenceError: b is not defined
Finally block always executes
示例
在下面的例子中,我们在 try{} 语句中编写了没有任何错误的代码。
同时,我们也添加了 catch{} 和 finally{} 语句。
输出显示它先执行了 try{} 语句中的代码,然后执行了 finally{} 语句中的代码。由于代码没有错误,它跳过了 catch{} 语句的执行。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
let a = 10;
output.innerHTML = "Value of a is " + a + "<br>";
} catch (e) {
output.innerHTML = e.name + " : " + e.message;
}
finally {
output.innerHTML += "Inside the finally block.";
}
</script>
</body>
</html>
输出
Value of a is 10
Inside the finally block.
JavaScript throw 语句
当代码中出现任何错误时,默认情况下 JavaScript 会抛出一个错误。但是你也可以手动抛出错误。例如,你正在做表单数据验证。如果数据无效,你可以抛出错误并要求用户更正数据。
当你使用 ‘throw’ 语句抛出一个错误时,try{} 语句中该语句之后的代码将不会被执行,并且会执行 catch{} 语句中的代码。
你可以遵循下面的语法使用 ‘throw’ 语句抛出一个错误。
throw <error>;
在上面的语法中, 可以是一个 ‘Error’ 对象、字符串、数字、原始值或某种类型的错误对象。抛出 Error 对象而不是原始值是一个好的做法。
示例:抛出 Error 对象
在下面的代码中,我们使用 ‘throw’ 语句从 try{} 语句中抛出一个 Error 对象。它停止了 ‘throw’ 语句之后的代码的执行,并执行了 catch{} 语句中的代码。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
output.innerHTML += "Start of the try block. <br />";
throw new Error("Custom error");
output.innerHTML += "End of the try block. <br />";
} catch (e) {
output.innerHTML += "Catch block: Caught exception. <br />";
output.innerHTML += e.name + " : " + e.message;
}
</script>
</body>
</html>
输出
Start of the try block
Catch block: Caught exception.
Error: Custom error
示例:抛出原始值
在下面的代码中,我们从 try{} 语句中抛出一个原始数值。在 catch{} 语句中,我们获取抛出的原始值并打印它。
<html>
<body>
<div id = "output">The error message is: </div>
<script>
try {
throw 20;
} catch (e) {
document.getElementById("output").innerHTML += e;
}
</script>
</body>
</html>
输出
The error message is: 20
示例:输入验证示例
在下面的代码中,我们定义了一个 number 类型的 元素来获取用户的年龄作为输入。
当用户点击提交年龄按钮时,它调用 handleAge() 函数。handleAge() 函数检查年龄是否小于 18。如果是,则抛出 rangeError。
catch{} 语句打印错误信息来验证年龄。
<html>
<body>
<p>Age: <input type = "number" id = "age" value = "20"></p>
<button onclick = "handleAge()"> Submit Age </button>
<p id = "demo"> </p>
<script>
const output = document.getElementById("demo");
function handleAge() {
let age = document.getElementById("age").value;
try {
if (age < 18) {
throw RangeError("You are not eligible to vote");
} else {
output.innerHTML += "<br>You are eligible to vote";
}
} catch (e) {
output.innerHTML += "<br>The error is - " + e;
}
}
</script>
</body>
</html>
输出
Age: 20
Submit Age
The error is - RangeError: You are not eligible to vote
嵌套 Try 块
有时,开发人员需要编写嵌套的 try-catch 语句。嵌套的 try-catch 意味着在一个 try 块内部还有一个 try 块。
如果内部的 catch{} 语句无法处理错误,外部的 catch{} 语句可能会处理它。你也可以省略内部的 catch{} 语句,但在这种情况下,你需要在 try{} 语句中写入 finally{} 语句。
JavaScript try...catch 语句
示例
我们在下面的代码中使用了两个嵌套的 try{} 语句。我们在外层 try{} 语句内添加了 try-finally 语句。
内部的 try{} 语句抛出的错误在外层的 catch{} 语句中处理。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
try {
throw Error("Error in the inner try block");
} finally {
output.innerHTML += "Inside the inner finally block. <br>";
}
} catch (e) {
output.innerHTML += "Inside the outer catch block. <br>";
output.innerHTML += "Error: " + e.message;
}
</script>
</body>
</html>
输出
Inside the inner finally block.
Inside the outer catch block.
Error: Error in the inner try block
重新抛出错误
有时候,catch{} 语句无法处理错误。在这种情况下,你可以使用 ‘throw’ 语句从 catch 块中重新抛出错误。
如果存在的话,外层的 catch{} 语句可以处理重新抛出的错误。
示例
在下面的代码中,我们创建了两个嵌套的 try-catch 块。在内部的 try 块中,我们使用 ‘throw’ 语句抛出错误。内部的 catch{} 语句捕获错误,并从内部的 catch{} 语句中重新抛出错误。
之后,在外层的 catch{} 语句中处理错误。
<html>
<body>
<div id = "demo"> </div>
<script>
let output = document.getElementById("demo");
try {
try {
throw 20;
} catch (e) {
output.innerHTML = "Inside the inner catch block. <br>";
output.innerHTML += "Error: " + e + "<br> <br>";
throw e;
}
} catch (e) {
output.innerHTML += "Inside the outer catch block. <br>";
output.innerHTML += "Error: " + e;
}
</script>
</body>
</html>
输出
inside the inner catch block.
Error: 20
Inside the outer catch block.
Error: 20
条件性 catch 块
在 catch{} 块内,你可以使用 if-else 语句有条件地处理错误。这样,你可以为多个 try{} 语句使用单一的 catch{} 语句。
在 catch{} 语句中,你可以使用 ‘instanceOf’ 操作符检查错误类型,并根据错误类型处理错误。
示例
在下面的代码中,我们在 try{} 语句内调用了 welcome 函数,而 welcome() 函数未定义。
在 catch{} 语句中,我们使用 ‘instanceOf’ 操作符检查错误类型,并根据错误类型在网页上打印消息。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
welcome();
} catch (e) {
if (e instanceof ReferenceError) {
output.innerHTML = "Reference error is occurred.";
} else if (e instanceof TypeError) {
output.innerHTML = "Type error is occurred.";
} else if (e instanceof RangeError) {
output.innerHTML = "Range error is occurred.";
} else if (e instanceof SyntaxError) {
output.innerHTML = "Syntax error is occurred.";
} else {
output.innerHTML = "Error is occurred.";
}
}
</script>
</body>
</html>
输出
Reference error is occurred.
使用 setTimeout() 方法的 JavaScript try...catch
使用 try-catch 语句与异步 JavaScript 代码一起时,不会捕获 try 块中抛出的错误。
原因是 JavaScript 在所有主线程代码执行完毕后才执行异步代码。
示例
在下面的代码中,我们在 try{} 语句内使用了 setTimeOut() 方法。它在 1000 毫秒后执行回调函数。在回调函数中,我们使用 ‘throw’ 语句抛出错误。
在输出中,你可以看到 catch{} 语句没有捕获错误,并且在浏览器的控制台中打印了错误。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
try {
output.innerHTML = "Inside the try block. <br>";
setTimeout(() => {
throw new Error("Whoops!");
}, 1000);
} catch (err) {
output.innerHTML += "Inside the catch block. <br>";
output.innerHTML = err;
}
</script>
</body>
</html>
输出
Inside the try block.
基于 Promise 的错误
当消费 promise 代码时发生任何错误,你可以使用 catch() 方法来处理错误。或者,你可以将错误处理器作为 then() 方法的第二个参数传递。
示例
在下面的代码中,我们创建了一个 promise 并在 1000 毫秒后拒绝它。
之后,我们使用 then() 和 catch() 方法来处理 promise。在这里,我们拒绝了 promise,因此控制权将执行 catch() 方法中的代码。
<html>
<body>
<div id = "demo"> </div>
<script>
const output = document.getElementById("demo");
output.innerHTML = "The promise is pending...";
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
reject("The promise is rejected!");
}, 1000);
});
promise
.then((result) => {
output.innerHTML = result;
})
.catch((error) => {
output.innerHTML = error;
});
</script>
</body>
</html>
输出
The promise is rejected !
JavaScript 中的错误类型
JavaScript 可以抛出不同类型的错误。在这里,我们将逐一了解每种类型的错误及其示例。
JavaScript RangeError
当值超出指定范围时,JavaScript 代码会抛出 RangeError。
示例
在下面的代码中,我们使用了 toPrecision() 方法并将 1000 作为参数传递。它抛出了 RangeError,因为数字不能有 1000 位。
<html>
<body>
<div id = "output"> </div>
<script>
try {
let num = 10;
num.toPrecision(1000);
} catch (err) {
document.getElementById("output").innerHTML = err;
}
</script>
</body>
</html>
输出
RangeError: toPrecision() argument must be between 1 and 100
JavaScript ReferenceError
当你尝试访问未定义的变量、函数、类方法等时会发生 ReferenceError。
示例
在下面的代码中,我们执行了 ‘window’ 对象的 test() 方法。这里,test() 方法未定义,因此它抛出了 ReferenceError。
<html>
<body>
<div id = "output"> </div>
<script>
try {
window.test();
} catch (err) {
document.getElementById("output").innerHTML = err;
}
</script>
</body>
</html>
输出
TypeError: window.test is not a function
JavaScript TypeError
如果在方法或操作符中使用了无效类型的值,JavaScript 代码会抛出 TypeError。
示例
在下面的示例中,我们将 toLowerCase() 方法与布尔变量一起使用,但 toLowerCase() 方法仅支持字符串值。因此,它抛出了 TypeError。
<html>
<body>
<div id = "output"> </div>
<script>
try {
let bool = true;
bool.toLowerCase();
} catch (err) {
document.getElementById("output").innerHTML = err;
}
</script>
</body>
</html>
输出
TypeError: bool.toLowerCase is not a function
JavaScript URIError
当没有将有效的 URL 作为 encodeURI、decodeURI 等方法的参数时,会引发 URIError。
示例
在下面的示例中,我们将无效的编码 URI 作为 decodeURI() 方法的参数。因此,它抛出了 URIError。
<html>
<body>
<div id = "output"> </div>
<script>
try {
decodeURI("%");
} catch (err) {
document.getElementById("output").innerHTML = err;
}
</script>
</body>
</html>
输出
URIError: URI malformed