文章简介
本文为【JavaScript 漫游】专栏的第 008 篇文章,记录了笔者所学习到的错误处理机制的所有知识点。
Error
实例对象- 原生错误类型,包括
SyntaxError
、ReferenceError
、RangeError
、TypeError
、URIError
对象 - 自定义错误
throw
语句try...catch
结构finally
代码块
Error
实例对象
JS 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JS 原生提供Error
构造函数,所有抛出的错误都是这个构造函数的实例。
var err = new Error('出错了');
err.message // '出错了'
JS 语言标准只提到,Error
实例对象必须有 message
属性,表示出错时的提示信息,没有提到其他属性。大多数 JS 引擎,对 Error
实例还提供 name
和 stack
属性,分别表示错误的名称和错误的堆栈,但它们是非标准的,不是每种实现都有。
message
:错误提示信息name
:错误名称stack
:错误的堆栈
使用 name
和 message
这两个属性,可以对发生什么错误有一个大概的了解。而 stack
属性用来查看错误发生时的堆栈。
原生错误类型
SyntaxError
对象是解析代码时发生的语法错误。
// 变量名错误
var 1a;
// Uncaught SyntaxError: Invalid or unexpected token
// 缺少括号
console.log 'hello');
// Uncaught SyntaxError: Unexpected string
ReferenceError
对象是引用一个不存在的变量时发生的错误。
// 使用一个不存在的变量
unknownVariable
// Uncaught ReferenceError: unknownVariable is not defined
RangeError
对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是 Number
对象的方法参数超出范围,以及函数堆栈超过最大值。
// 数组长度不得为负数
new Array(-1)
// Uncaught RangeError: Invalid array length
TypeError
对象是变量或参数不是预期类型时发生的错误。
new 123
// Uncaught TypeError: number is not a func
var obj = {};
obj.unknownMethod()
// Uncaught TypeError: obj.unknownMethod is not a function
调用对象不存在的方法,也会抛出 TypeError
错误。
URIError
对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及 encodeURI
、decodeURI
、encodeURIComponent
、decodeURIComponent
、escape
和 unescape
这六个函数。
decodeURI('%2')
// URIError: URI malformed
自定义错误
除了 JS 原生提供的错误对象,还可以定义自己的错误对象。
function UserError(message) {this.message = message || '默认信息';this.name = 'UserError';
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;new UserError('这是自定义的错误');
throw 语句
throw
语句的作用是手动中断程序执行,抛出一个错误。
if (x <= 0) {throw new Error('x 必须为正数');
}
// Uncaught ReferenceError: x is not defined
throw
也可以抛出自定义错误。
function UserError(message) {this.message = message || '默认信息';this.name = 'UserError';
}
throw new UserError('出错了!');
// Uncaught UserError {message: "出错了!", name: "UserError"}
实际上,throw
可以抛出任何类型的值,比如数值、字符串、布尔值等,对于 JS引擎来说,遇到 throw
语句,程序就中止了。引擎会接收到 throw
抛出的信息,可能是一个错误实例,也可能是其他类型的值。
try...catch
结构
一旦发生错误,程序就中止执行了。JS 提供了 try...catch
结构,允许对错误进行处理,选择是否向下执行。
try {throw new Error('出错了');
} catch (e) {console.log(e.name + ': ' + e.message);console.log(e.stack);
}
try...catch
可以嵌套。为了捕捉不同类型的错误,catch
代码块之中可以加入判断语句。
try {obj.fn();
} catch (e) {if (e instanceof EvalError) {console.log(e.name + ': ' + e.message);} else if (e instanceof RangeError) {console.log(e.name + ': ' + e.message);}// ...
}
finally
代码块
try...catch
结构允许在最后添加一个finally
代码块,表示不管是否出现错误,都必需在最后运行的语句。即便是 try
代码块中有 return
语句,finally
代码块也会执行。
function cleansUp() {try {throw new Error('出错了……');console.log('此行不会执行');} finally {console.log('完成清理工作');}
}
而且是先执行 finally
代码块,再执行 return
语句。
var count = 0;
function countUp() {try {return count;} finally {count++;}
}
countUp()
// 0
count
// 1