
文章简介
本文为【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