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