js错误类型及处理

218 阅读3分钟

js错误类型

JavaScript 在解析或运行时,一旦发生错误,代码通常会停止执行,引擎会抛出一个错误对象。所有抛出的错误都是JavaScript原生提供Error构造函数的实例。

Error对象的属性:

  • name:错误名称
  • message:错误详细提示信息
  • stack: 当前的调用栈:用于调试的,一个包含引发异常的嵌套调用序列的字符串。用于追踪错误来源。

Error实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象。也就是说,存在Error的6个派生对象。

1. SyntaxError语法错误

SyntaxError是代码解析时发生的语法错误。例如, 写了一个错误的语法var a =


function fn() {
    var a =
}
// Uncaught SyntaxError: Unexpected token }
fn()

2. TypeError 类型错误

TypeError是变量或者参数不是预期类型时发生的错误。例如在number类型上调用array的方法。


var n = 1234
a.concat(9)
// Uncaught TypeError: a.concat is not a function

3. RangeError 范围错误

RangeError是一个值超过有效范围发生的错误。例如设置数组的长度为一个负值。

// 数组长度不得为负数 new Array(-1)
// Uncaught RangeError: Invalid array length

4.ReferenceError 引用错误

ReferenceError是引用一个不存在的变量时发生的错误。

// Uncaught ReferenceError: mmm is not defined
console.log(mmm)

5. URIError

在 URI 函数中使用了非法字符,则 URIError 被抛出:

decodeURI("%%%"); //您无法对这些百分号进行 URI 编码\
// Uncaught URIError: URI malformed

6. EvalError

已在 eval() 函数中发生的错误,eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再使用了,有时候只是为了保证与以前代码兼容,才继续保留。一般使用 SyntaxError 代替

自定义错误

除了 JavaScript 原生提供的几种错误对象,还可以定义自己的错误对象。

function UserError(message) {
    this.message = message || '默认信息';
    [this.name](http://this.name/) = 'UserError';
}

UserError.prototype = new Error();
UserError.prototype.constructor = UserError;

上面代码自定义一个错误对象UserError,让它继承Error对象。然后,就可以生成这种自定义类型的错误了

new UserError('这是自定义的错误!');

js错误处理

常见的错误处理方式:

  • 使用局部使用try..catch捕获处理错误;
  • 使用window.onerror捕获全局错误,收集错误信息;

1. try..catch局部捕获

比起一段代码会在出错的时候“死掉”(停止执行)并在控制台将异常打印出来。有一种更为合理的语法结构 try..catch,它会在捕捉到异常的同时不会使得代码停止执行而是可以做一些更为合理的操作。比如重新请求、提示用户、把异常信息发送给记录日志的工具等。

try {
// 要执行的代码...
} catch (err) {
// err是javescript引擎抛出的错误对象,Error的实例
// 异常处理
}

它按照以下步骤执行:

  • 首先,执行 try {...} 里面的代码。
  • 如果执行过程中没有异常,那么忽略 catch(err) 里面的代码,try 里面的代码执行完之后跳出该代码块。
  • 如果执行过程中发生异常,控制流就到了 catch(err) 的开头。变量 err(可以取其他任何的名称)是一个包含了异常信息的对象。 没有异常:
try {
  console.log('Start of try runs'); // (1) <--
  // ...这里没有异常
  console.log('End of try runs'); // (2) <--
} catch(err) {
  console.log('Catch is ignored, because there are no errors'); // (3)
}
console.log("...Then the execution continues"); // (4) <--

有异常:

try {
  console.log('Start of try runs'); // (1) <--
  lalala; // 异常,变量未定义!
  console.log('End of try (never reached)'); // (2)
} catch(err) {
  console.log(`Error has occured!`); // (3) <--
}
console.log("...Then the execution continues"); (3) <--

注意:

  1. 要使得 try..catch 能工作,代码必须是可执行的,换句话说,它必须是有效的 JavaScript 代码。如果代码包含语法错误,那么 try..catch 不能正常工作,例如含有未闭合的花括号:
try {
{{{{{{{{{{{{
} catch(e) { alert("The engine can't understand this code, it's invalid"); }
  1. catch只能捕获事件队列中的同步任务,异步任务中的异常无法捕获,例如在 setTimeout 中,那么 try..catch 不能捕捉到:
try {
  setTimeout(function() {
    noSuchVariable; // 代码在这里停止执行
  }, 1000);
} catch (e) {
  alert( "won't work" );
}

异步任务setTimeout执行时,引擎已经离开了 try..catch 结构,要捕获到setTimeout执行的异常,try..catch要在setTimeout之中

setTimeout(function() {
    try {
      noSuchVariable; // try..catch 处理异常!
    } catch (e) {
      alert( "error is caught here!" );
    }
}, 1000);

throw Error

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

if (x <= 0) {
 throw new Error('x 必须为正数');
}
// Uncaught ReferenceError: x is not defined

实际上,throw可以抛出任何类型的值。也就是说,它的参数可以是字符串、数字、布尔、对象等任何类型。为了方便开发者了解错误信息,最好抛出一个错误实例。方便追踪错误原因和来源。

throw也可以抛出自定义的错误实例。

function UserError(message) {
    this.message = message || '默认信息';
    [this.name](http://this.name/) = 'UserError';
}

throw new UserError('出错了!');
// Uncaught UserError {message: "出错了!", name: "UserError"}

trycatchfinally

finally里的代码无论是否有异常抛出或捕获它总是执行。

在try和catch的代码块中,如果碰到return语句,那么在return之前,会先执行finally中的内容,如果finally里有return语句,那么就真的return了。

function test() {
    try {
    console.log(1);
    throw new Error('throw');
    } catch (e) {
    console.log(e.message);
    return 'from_catch';
    } finally {
    console.log(2);
    return 'from_finally'
    }
}

console.log(test()); // 1 throw 2 from_finally

try..finally 结构也很有用,当我们希望确保代码执行完成不想在这里处理异常时,我们会使用这种结构,但是finally之后的代码就不会执行

function func() {
    try {
    console.log(a)
    } finally {
    console.log('finally')
    }
    console.log('func')
}
func() // finally

2. window.onerror 全局捕获

window.onerror 的目的不是去处理整个代码的执行中的所有异常 —— 这几乎是不可能的,这只是为了给开发者提供异常信息。

语法:


window.onerror = function(message, url, line, col, error) {
// ...
};

参数:

  • message:异常信息。
  • url:发生异常的代码的 URL。
  • line, col:错误发生的代码的行号和列号。
  • error:异常对象。
  • 常用的错误监控服务

总结

  1. js运行时发生错误,会停止代码执行,js引擎抛出错误,所有的错误继承Error对象;
  2. 常见的错误类型有: SyntaxError语法错误、 TypeError 类型错误、RangeError; 范围错误、ReferenceError引用错误、URIError URI函数错误
  3. 我们可以使用try..catch捕获js错误,使代码继续执行并在catch进行错误处理;
  4. window.onerror全局捕获error, 通常给开发者提供信息。

参考来源:

zh.javascript.info/try-catch#t…

zhuanlan.zhihu.com/p/63510452

zhuanlan.zhihu.com/p/92914399