🔦 JavaScript 的错误处理
# try...catch 结构
try {
// 代码...
} catch (err) {
// 错误捕获
}
2
3
4
5
6
7
8
9
其中 err 将包含一个 error 对象,该对象包含了所发生事件的详细信息。
🌰 例子:
try {
console.log('Start of try runs'); // (1) <--
lalala; // Error,变量未定义!
console.log('End of try (never reached)'); // (2)
} catch (err) {
console.log(err); // (3) <--
}
2
3
4
5
6
7
提示
try...catch 仅对运行时的 error 有效。
要使得 try...catch 能工作,代码必须是可执行的。换句话说,它必须是有效的 JavaScript 代码。如果代码包含语法错误,那么 try..catch 将无法正常工作(编译错误)。
try...catch 只能处理有效代码中出现的错误(运行错误),或者为 异常。
提示
在使用如 setTimeout 定时器 计划的代码时,应该:
setTimeout(function() {
try {
noSuchVariable; // try...catch 处理 error 了!
} catch {
alert( "error is caught here!" );
}
}, 1000);
2
3
4
5
6
7
如果在 setTimeout 外部使用则捕获不了错误,因为引擎已经离开了 try ... catch 结构。
# Error 对象
发生错误时,JavaScript 生成包含错误有关其详细信息的对象,作为参数传送给 catch 。
内建的 Error 对象中包含:
name:``Error` 名称。message:关于错误的详细文字描述。stack:当前的调用栈:用于调试目的的一个字符串,其中包含有关导致 error 的嵌套调用序列的信息。
🌰 例子:
try {
lalala; // error, variable is not defined!
} catch (err) {
alert(err.name); // ReferenceError
alert(err.message); // lalala is not defined
alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)
// 整体错误对象输出
alert(err); // ReferenceError: lalala is not defined
}
2
3
4
5
6
7
8
9
10
提示
新增的 JavaScript 特性中,可以不使用 Error 对象:
try {
// ...
} catch {
// ...
}
2
3
4
5
# 抛出 Error 对象
使用 throw 操作符会生成一个 error 对象。
🌰 例子:
let json = '{ "age": 30 }'; // 不完整的数据
try {
let user = JSON.parse(json);
if (!user.name) {
throw new SyntaxError("Incomplete data: no name");
}
alert( user.name );
} catch(err) {
alert( "JSON Error: " + err.message ); // JSON Error: Incomplete data: no name
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
再次抛出错误 Error 对象: catch 应该只处理它知道的 error,并在此抛出所有其他 error。
🌰 例子:
let json = '{ "age": 30 }'; // 不完整的数据
try {
let user = JSON.parse(json);
if (!user.name) {
throw new SyntaxError("Incomplete data: no name");
}
blabla(); // 预料之外的 error
alert( user.name );
} catch (err) {
if (err instanceof SyntaxError) {
alert( "JSON Error: " + err.message );
} else {
throw err; // 再次抛出 (*)
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
catch中只处理了SyntaxError,对于其他错误,再次抛出,交由外部的try…catch结构处理,如果没有被处理则 脚本就会被杀死。
# finally
finally 子句通常用在:当开始做某事的时候,希望无论出现什么情况都要完成完成某个任务。
无论是 有无出现错误,都会执行
finally中的工作。
🌰 例子:
try {
confirm( 'try' );
if (confirm('Make an error?')) BAD_CODE();
} catch (err) {
console.log( 'catch' );
} finally {
console.log( 'finally' );
}
2
3
4
5
6
7
8
提示
注意 try 中的局部变量。如果在 try 中声明变量(使用 let ),那么该变量只能在 try 中使用可见。 finally 中不可见。
在
try中的return:try { return 1; } catch (err) { /* ... */ } finally { console.log( 'finally' ); }1
2
3
4
5
6
7此时,先执行
finally中的代码,再执行return。只用
try...finally:当不想再
try结构中处理错误,但是要确保finally中的代码要执行:try{ // ... } finally { // ... }1
2
3
4
5由于没有
catch,所以try中的 error 总是会使代码执行跳转至函数func()外。但是,在跳出之前需要执行finally中的代码。
# 全局 catch
即使没有 try...catch ,大多数执行环境也允许设置全局错误处理程序来捕获 出错对象。在浏览器中,就是 window.onerror 。
