🔦 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
。