JavaScript Error
Error类型
Error类型
ECMAScript定义了几种错误类型:
Error
: 所有错误类型的基类,其他错误类型都继承该类型。[EvalError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/EvalError)
: 创建一个 error 实例,表示错误的原因:与[eval()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval)
有关。[RangeError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RangeError)
:创建一个 error 实例,表示错误的原因:数值变量或参数超出其有效范围。[ReferenceError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)
:创建一个 error 实例,表示错误的原因:无效引用。[SyntaxError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError)
:创建一个 error 实例,表示错误的原因:语法错误。[TypeError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/TypeError)
:创建一个 error 实例,表示错误的原因:变量或参数不属于有效类型。[URIError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/URIError)
:创建一个 error 实例,表示错误的原因:给[encodeURI()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/encodeURI)
或[decodeURI()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/decodeURI)
传递的参数无效。[AggregateError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/AggregateError)
: 创建一个 error 实例,其中包裹了由一个操作产生且需要报告的多个错误。如:[Promise.any()](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/any)
产生的错误。[InternalError](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/InternalError)
非标准: 创建一个代表 Javascript 引擎内部错误的异常抛出的实例。如:递归太多。
识别Error类型
不同的错误类型可用于为异常提供更多信息,以便实现适当的错误处理逻辑,如果你需要识别错误类型,可以在catch块中通过instanceof来判断error对象的类型。
try{
const a = 1;
a = 2;
}catch(error){
console.log(error instanceof TypeError);
// true
}
抛出错误
抛出错误需要用到throw操作符,它可以抛出任何值,并且js一旦执行throw语句,就会立即停止执行,除非try…catch语句捕捉了抛出的异常。
// throw抛出的值类型不限
throw 1
throw '1'
throw {a: 1}
throw true
但是通常我们最好抛出一个错误对象来模拟浏览器错误,抛出一个错误对象比直接抛出一个值(例如字符串)更好的地方在于前者会包含调用栈等信息,以便后续修复异常。
(function(){
let a = 123;
throw new Error(123)
})()
/*
VM2736:1 Uncaught Error: 123
at <anonymous>:1:32
at <anonymous>:1:50
(匿名) @ VM2736:1
(匿名) @ VM2736:1
*/
抛出一个错误对象很简单,只需要通过实例化一个内置错误类即可,通常是Error,因为其他的错误类都是继承于Error,你只需要传递一个参数message,即错误消息。message是可选的,但是通常我们都会传,以便更好地处理错误。
function sort(arr){
if(!Array.isArray(arr)){
throw new Error('参数类型错误,你应当传递一个数组类型')
}
return arr.sort((a,b)=> a-b);
}
sort(1);
// Uncaught Error: 参数类型错误,你应当传递一个数组类型
当然你也可以抛出一个具体的错误对象,例如上面这里例子中使用TypeError可以更好地表示是类型错误。
throw new TypeError('你应当传递一个数组类型')
// Uncaught TypeError: 你应当传递一个数组类型
除了Error和其他内置错误对象,你还可以自定义Error类型。
自定义Error类型
创建一个自定义Error类型很简单,只需要实现一个继承Error的类,并实现message属性和name属性即可。
class CustomError extends Error {
constructor(name='CustomError ', message) {
super();
this.name = name;
this.message = message;
}
}
示例:
下面这个实例中实现了一个自定义Error类型CustomError,在输入框中输入CustomError.name和CustomError.message后点击抛出异常按钮,你应当可以在控制台看到错误信息。
https://codesandbox.io/s/zi-ding-yi-cuo-wu-lei-xing-nj0c9g
捕获异常
try…catch…finally
try…catch可以捕获异常,当try块中发生错误时,代码会立即退出执行,并跳到catch块中执行,catch块此时会接收到一个错误对象,该错误对象包含错误的相关信息,这个错误对象中的信息根据浏览器而异,但是它至少会包含message属性。
try{
const a = 1;
a++; // 产生一个错误
console.log(1) // 不会执行
}catch(err){
// 错误对象是必须要声明的,即使你不用它
}
finally块是可选的,无论是否发生错误,finally块的代码都会执行,并且try或catch块都无法阻止finally块的执行。
function fn(){
try{
return 1;
}catch(err){
return 2;
}finally{
console.log(3)
}
}
fn() // 3
window.onerror
任何没有被try…catch捕获的异常都会传递到window.onerror事件上,在onerror事件处理程序上通常有这么几个参数:
错误消息message
错误文档的URL
错误发生的行号
错误发送的列号
错误对象
如果window.onerrror事件处理程序中返回为true,那么控制台将不会打印错误信息,即:
window.onerror = function (message, url, lno, cno, error) {
console.table({
message,
url,
lno,
cno,
error
});
return true;
}
window.onerror是处理错误的最后一道防线,可以在此将异常上报,以便后续追踪修复。
更多信息见:前端监控方案
新特性
Error Cause
Error Cause当前已经到达第四阶段,Error Cause的作用是在从深层内部逻辑引发的错误时,能够将错误对象一同抛出,以此来增强错误描述。
可以看下这个例子:
// 私有函数
function _sort(arr) {
return arr.sort((a, b) => a - b)
}
export function sort(arr) {
// ... 处理某些逻辑
try {
_sort(arr)
} catch (err) {
throw new Error('执行sort错误,原因是'+ err.message)
}
}
sort(1)
// Uncaught Error: 执行sort错误,原因是arr.sort is not a function
在这个例子中,我们提前预见_sort
函数的执行可能会出现异常,因此我们用try…catch捕获异常,但是我们并不能提前预判是哪种异常,因此我们只能提示有错误,并将错误消息(即err.message
)一同显示。但是这种并不是很友好,因为err错误对象只有错误消息被传递,由于错误是深层的,错误堆栈不会追踪到_sort
函数,除非我们去_sort
函数源码,否则我们很难判断错误发送的原因,但是Error Cause能够将错误对象一同携带出来,我们可以通过错误对象的错误堆栈来快速地追踪到错误。
使用error cause很简单,只需要在Error实例化时第二个参数传递一个包含cause属性的对象,而cause属性的值就是错误对象。
function _sort(arr) {
return arr.sort((a, b) => a - b)
}
function sort(arr) {
// ... 处理某些逻辑
try {
_sort(arr)
} catch (err) {
throw new Error('执行sort错误', {
cause: err
})
}
}
sort(1)
Uncaught Error: 执行sort错误
sort http://127.0.0.1:5500/error.html:75
<anonymous> http://127.0.0.1:5500/error.html:81
Caused by: TypeError: arr.sort is not a function
_sort http://127.0.0.1:5500/error.html:67
sort http://127.0.0.1:5500/error.html:73
<anonymous> http://127.0.0.1:5500/error.html:81
当使用Error Cause后,_sort
函数错误堆栈也能被打印出来,可以很快的锁定错误。
参考
《JavaScript高级程序设计第四版》
Window: error event - Web API 接口参考 | MDN (mozilla.org)
Error - JavaScript | MDN (mozilla.org)
最后更新于