Skip to content

JS 的错误处理机制

JS 代码解析运行时,一旦发现错误,JS 引擎就会抛出Error对象。

Error 对象包括 message 错误信息 name 错误名 stack 错误堆栈 三个属性 (这三个属性不是标准,并非所有 JS 引擎都有)

js
try {
    throw new Error('my error')
} catch (e) {
    console.log(e.stack)
    // Error: my error
    //     at playground.html:13:19
}

常见的原生错误类型

名称说明
SyntaxError语法错误,通常在解析代码时发生
ReferenceError引用错误,比如使用不存在的变量
RangeError有效范围错误,比如无限递归栈溢出, 数组length不合理
TypeError类型错误,比如把一个原始类型当作方法调用,访问undefined的属性
URIErrorencodeURI encodeURIComponent 等函数报错

throw

throw 语句可以手动抛出错误

try..catch

catch中捕获错误,并进行相应处理

finally

try..catch的最后添加 finally 代码块,这是一段无论是否出错必然会在最后运行的一段代码块。

具体体现为:

  • 错误被成功处理了, finally块正常执行
  • 错误未捕获, 从错误代码跳出 --> 执行完finally代码块 --> 控制台报错,中断后序代码执行
  • finally 中的 return 会覆盖 try catch 中的 return,只要 finally 块代码块不抛出错误,正常return跳出函数,后序主逻辑代码均正常执行
js
// 错误被成功处理了,finally正常执行
function fn1() {
    try {
        console.log(1)
        throw "something wrong" // 遇到错误,直接跳到catch
        console.log(2)
        return 'hello'
    } catch (e) {
        console.log(e) 
    } finally {
        console.log(3) // 必然执行
    }
}
const res = fn1() // 1, something wrong, 3
console.log(res) // undefined
js
// 错误未捕获, 从错误代码跳出 --> 执行完finally代码块 --> 控制台报错,中断后序代码执行
function fn2() {
    try {
        console.log(1)
        throw "something wrong" // 遇到错误,直接跳到catch
        console.log(2)
        return 'hello'
    } finally {
        let now = Date.now()
        while (Date.now() - now < 5000) {
            // donothing
        }
        console.log('3')
    }
}
const res = fn2() // 1, 等待5秒后打印3
// 然后,控制台报错 Uncaught something wrong
console.log('res :', res) // 没执行,没有打印任何东西
js
// finally 中的 return 会覆盖 try catch 中的 return
function fn3() {
    try {
        console.log(0)
        throw "bug" // 遇到错误,直接跳到catch
        return 'aaa'
    } catch (e) {
        console.log(1)
        return 'bbb'
        console.log(2)
    } finally {
        console.log(3)
        return 'ccc'
        console.log(4)
    }

    console.log(5)
}

const res = fn3() // 0, 1, 3
console.log(res) // 'ccc'


// 只要 finally 块代码块不抛出错误,正常return跳出函数,后序主逻辑代码均正常执行
function fn4() {
    try {
        throw "from try";
    } catch (e) {
        console.log("catch", e);
        throw "from catch" // catch 抛错
    } finally {
        return "from finally";
    }
    console.log("ending"); // 不会执行
}
const r = fn4()
console.log("result:", r);

// 正常执行后序主逻辑
console.log(1 + 1)