JavaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供Error构造函数,所有抛出的错误都是这个构造函数的实例

  1. var err = new Error('出错了');
  2. err.message // "出错了"
  • message:错误提示信息
  • name:错误名称(非标准属性)
  • stack:错误的堆栈(非标准属性)

原生错误类型

SyntaxError

var err = new Error'出错') // SyntaxError: Unexpected string

ReferenceError

对象是引用一个不存在的变量时发生的错误,或将一个值分配给无法分配的对象,比如对函数的运行结果或者this赋值

unknownVariable // Uncaught ReferenceError: unknownVariable is not defined

this = 1 // ReferenceError: Invalid left-hand side in assignment

RangeError

RangeError对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值

new Array(-1) // Uncaught RangeError: Invalid array length

TypeError

TypeError对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new命令,就会抛出这种错误,因为new命令的参数应该是一个构造函数

  1. new 123
  2. // Uncaught TypeError: number is not a func
  3. var obj = {};
  4. obj.unknownMethod()
  5. // Uncaught TypeError: obj.unknownMethod is not a function

URIError

URIError对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()、decodeURI()、encodeURIComponent()、decodeURIComponent()、escape()和unescape()这六个函数

EvalError

eval函数没有被正确执行时,会抛出EvalError错误

以上这6种派生错误,连同原始的Error对象,都是构造函数。开发者可以使用它们,手动生成错误对象的实例。这些构造函数都接受一个参数,代表错误提示信息(message)

  1. var err1 = new Error('出错了!');
  2. var err2 = new RangeError('出错了,变量超出有效范围!');
  3. var err3 = new TypeError('出错了,变量类型无效!');
  4. err1.message // "出错了!"
  5. err2.message // "出错了,变量超出有效范围!"
  6. err3.message // "出错了,变量类型无效!"

自定义错误

  1. function UserError(message) {
  2. this.message = message || '默认信息';
  3. this.name = 'UserError';
  4. }
  5. UserError.prototype = new Error();
  6. UserError.prototype.constructor = UserError;
  7. console.log(new UserError('出错').message)

throw 语句

throw语句的作用是手动中断程序执行,抛出一个错误

对于 JavaScript 引擎来说,遇到throw语句,程序就中止了。引擎会接收到throw抛出的信息,可能是一个错误实例,也可能是其他类型的值

  1. var x=0
  2. if(x<1){
  3. //throw new Error('数值范围错误')
  4. //throw new UserError('出错').message
  5. throw 123 //123
  6. }

try…catch

如果你不确定某些代码是否会报错,就可以把它们放在try…catch代码块之中,便于进一步对错误进行处理。
为了捕捉不同类型的错误,catch代码块之中可以加入判断语句。

  1. try {
  2. foo.bar();
  3. } catch (e) {
  4. if (e instanceof EvalError) {
  5. console.log(e.name + ": " + e.message);
  6. } else if (e instanceof RangeError) {
  7. console.log(e.name + ": " + e.message);
  8. }
  9. // ...
  10. }

finally

try…catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。

  1. function idle(x) {
  2. try {
  3. console.log(x);
  4. return 'result';
  5. } finally {
  6. console.log('FINALLY');
  7. }
  8. }
  9. idle('hello')
  10. // hello
  11. // FINALLY

return语句的执行是排在finally代码之前,只是等finally代码执行完毕后才返回

  1. var count = 0;
  2. function countUp() {
  3. try {
  4. return count;
  5. } finally {
  6. count++;
  7. }
  8. }
  9. countUp()
  10. //1
  1. function f() {
  2. try {
  3. console.log(0);
  4. throw 'bug';
  5. } catch(e) {
  6. console.log(1);
  7. return true; // 这句原本会延迟到 finally 代码块结束再执行
  8. console.log(2); // 不会运行
  9. } finally {
  10. console.log(3);
  11. return false; // 这句会覆盖掉前面那句 return
  12. console.log(4); // 不会运行
  13. }
  14. console.log(5); // 不会运行
  15. }
  16. var result = f();
  17. // 0 1 3