JS基础之错误处理机制

328 阅读3分钟

JS错误处理机制

原生错误类型:

1. SyntaxError对象

SyntaxError对象是解析代码时发生的语法错误。

// 变量名错误
var 1a;
// Uncaught SyntaxError : Invalid or unexpected token

// 缺少括号
console.log'hello world');
// Uncaught SyntaxError: Upexpected string

2. ReferenceError对象

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

// 使用一个不存在的变量
unknownVariable
// Uncaught ReferenceError: unkonwnVariable is not defined

另一种触发场景是,将一个值分配给无法分配的对象,如对函数的运行结果赋值。

// 等号左边不是变量
console.log() = 1
// Uncaught ReferenceError: Invalid left-hand side in assignment

3. RangeError对象

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

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

4. TypeError对象

TypeError对象是变量或参数不是预期类型时发生的错误。

// new 命令的参数应该是一个构造函数
new 123
// Uncaught TypeError: 123 is not a constructor
var obj = {}
obj.unknownMethod()
// Uncaught TypeError: obj.unknownMethod is not a function
// 也会抛出TypeError错误,因为obj.unknownMethod的值是undefined

5. URIError对象

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

decodeURI('%2)
// URIError: URI malformed

6. EvalError对象

eval函数没有被正确执行时,会抛出EvalError错误。该错误类型已经不再使用,只是为保证与以前代码兼容才继续保留。

总结

以上6中派生错误,连同原始的Error对象,都是构造函数。都接受一个参数,代表错误提示信息(message)。

自定义错误

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

function UserError(message) {
    this.message = message || '默认信息'
    this.name = 'UserError
}

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

上面代码自定义了一个错误对象UserError,继承了Error对象。

// 生成的自定义错误对象
new UserError('自定义的错误对象')

throw 语句

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

var x = -1
if (x <= 0) {
    throw new Error('x必须为正数')
}
// Uncaught Error: x必须为正数

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

try...catch 结构

JavaScript提供了try...catch结构,允许对错误进行处理,选择是否往下执行程序。

try() {
    throw new Error('出错了')
} catch(e) {
    console.log(e.name + ':' + e.message)
    console.log(e.stack)
}

上面代码中,try代码块抛出错误,JavaScript引擎立即把代码的执行转到catch代码块,或者说错误被catch代码块捕获了。catch接受一个参数,表示try抛出的值。
catch代码块捕获错误后,程序不会中断,会按照正常流程继续执行下去。

finally 代码块

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

function cleanUp() {
    try {
        throw new Error('出错了')
        console.log('此行不会执行')
    } finally() {
        console.log('完成')
    }
}
cleanUp()
// 完成
// Uncaught Error: 出错了
// ...

上面代码中由于没有catch语句块,一旦发生错误则中断执行。在中断执行之前,会先执行finally代码块。

下面的例子反映了try...catch...finally三者之间的执行顺序。

function f() {
    try {
        console.log(0)
        throw 'bug'
    } catch(e) {
        console.log(1)
        return true        // 这句原本会延迟到 finally 代码块结束再执行
        console.log(2)     // 不会执行
    } finally {
        console.log(3)
        return false      // 这句会覆盖前面那句 return
        console.log(4)    // 不会执行
    }
    console.log(5)       // 不会执行
}

var result = f()
// 0
// 1
// 3

result
// false