likes
comments
collection
share

JavaScript 高级深入浅出:异常处理

作者站长头像
站长
· 阅读数 15

介绍

本文是 JavaScript 高级深入浅出的第 18 篇,本文将会介绍 JS 中的异常处理

正文

1. 异常处理方案

开发中我们会封装一些工具函数,封装之后供别人使用:

  • 在使用过程中,可能会向这个工具函数传递一些参数
  • 对于函数而言,需要校验参数,否则可能不是我们想要的结果

很多时候如果不是我们想要的结果,可能就直接 return 了,但是 return 有弊端:

  • 调用者不知道函数没有正常执行,直接返回了 undefined
  • 事实上,正确的做法是如果没有通过某些验证,那么就应该直接告诉外界错误
// 比如我们编写一个工具函数
function double(number) {
  if (typeof number !== 'number') {
    return
  }
  return number * 2
}

// 这里调用的时候,参数传递错误了
const doubleNumber = double('你好')
// 所以 doubleNumber 就是 undefined
// 没有报错,那么后续的逻辑仍然会运作,这就是弊端

所以我们该如何告诉外界呢:

  • 使用 throw 来抛出一个异常

throw 语句:

  • 用于抛出用户自定义的异常
  • 当遇到 throw 语句后,throw 后面的代码将不会执行

所以在函数未通过某些验证的时候,使用 throw 抛出错误才是正确的解决方案

// 那么我们就可以改造一下
function double(number) {
  if (typeof number !== 'number') {
    // 这里直接抛出一个错误
    throw new TypeError('Expected a number, bug got ' + typeof number)
  }
}

const doubleNumber = double('你好')
// 如果不对上述代码进行异常捕获,那么后续的逻辑将不再执行

2. throw 关键字

thorw 表达式就是在 throw 的后面跟上一个表达式来表示具体的异常信息:

  • throw expression

throw 关键字可以跟上什么类型呢?

  • 基本数据类型:number、string、boolean
  • 对象类型:对象类型可以包含更多的信息
throw 1
throw "error"
throw false

throw {
    errorCode: '2001',
    msg: "error"
}

但是我们每次都要手动创建一个对象很麻烦,所以可以封装为一个类:

class MyError {
    constructor(errorCode, errorMsg) {
        this.errorCode = errorCode
        this.errorMsg = errorMsg
    }
}

throw new MyError("2001", 'error')

3. Error 类

在 JS 中其实封装了一个类,方面我们抛出异常用:

throw new Error('error msg')

一个 Error 实例包含三个属性:

  • message:创建 Error 对象时传入的参数
  • name:Error 实例的名称,通常和类名一致
  • stack:整个 Error 的错误信息,包含函数的调用栈,当我们直接打印 Error 对象时,打印的就是 stack

同时 Error 也有子类:

  • RangeError:索引值越界时使用的错误类型
  • SyntaxError:解析语法错误使用的错误类型
  • TypeError:出现类型错误时使用的错误类型

4. 捕获异常

当我们使用某个函数时,若函数内容抛出了异常,那么为了保证后面的代码继续运行,就需要我们来手动捕获异常,捕获异常使用 try...catch 语句

try...catch语句结构:

try {
    try_statements
}
[catch (exception_var_1) {
    catch_statements_1
}]
[finally {
 	finally_statements
}]

样例:

function foo() {
  throw new Error('error')
}

try {
  foo()
} catch (error) {
  console.log('error') // foo 函数的异常进入到这里进行处理
} finally {
  // finally 一般不写
  console.log('always execute') // 不管是否有异常,都会执行这里'
}

console.log('code') // 运行

顺便一提,从 ES10 开始, catch 可以不写参数了

try {
    
} catch {
    
}

总结

在本文中,你学到了:

  • 正确处理函数边界情况的方式,抛出异常
  • throw 关键字
  • Error 以及 子类
  • 如何捕获异常