# 错误处理方案
- 很多时候我们可能验证到不是希望得到的参数时,就会直接 return:
- 但是 return 存在很大的弊端:调用者不知道是因为函数内部没有正常执行,还是执行结果就是一个 undefined;
- 事实上,正确的做法应该是如果没有通过某些验证,那么应该让外界知道函数内部报错了;
- 如何可以让一个函数告知外界自己内部出现了错误呢?
- throw 语句:
- throw 语句用于抛出一个用户自定义的异常;
- 当遇到 throw 语句时,当前的函数执行会被停止(throw 后面的语句不会执行);
- 如果我们执行代码,就会报错,拿到错误信息的时候我们可以及时的去修正代码。
- 当我们有一个函数,在调用这个函数时,如果出现了错误,那么我们应该去修复这个错误
| function sum(m, n) { |
| |
| if (typeof m !== "number" || typeof n !== "number") { |
| throw "parameters is error type~" |
| } |
| |
| return m + n |
| } |
| |
| |
| console.log(sum({ name: "why" }, true)) |
| |
| |
| console.log("后续的代码会继续运行~") |
# throw 关键字
- throw 表达式就是在 throw 后面可以跟上一个表达式来表示具体的异常信息:
- throw 关键字可以跟上哪些类型呢?
- 基本数据类型:比如 number、string、Boolean
- 对象类型:对象类型可以包含更多的信息
# 抛出一个字符串类型 (基本的数据类型)
| function foo(type) { |
| console.log("foo函数开始执行") |
| if (type !== 'string') { |
| throw "error" |
| } |
| console.log("foo函数结束执行") |
| } |
| |
| foo('saber') |
# 抛出一个对象类型
| function foo() { |
| console.log("foo函数开始执行") |
| |
| throw {errorCode: 404, errorMessage: "所请求的页面不存在或已被删除" } |
| console.log("foo函数结束执行") |
| } |
| |
| foo() |
# 创建类,并且创建这个类对应的对象
- 如上面每次写这么长的对象又有点麻烦,所以我们可以创建一个类
| class _Error { |
| constructor(errorCode, errorMessage) { |
| this.errorCode = errorCode |
| this.errorMessage = errorMessage |
| } |
| } |
| |
| function foo() { |
| console.log("foo函数开始执行") |
| throw new _Error({errorCode: 404, errorMessage: "所请求的页面不存在或已被删除" }) |
| console.log("foo函数结束执行") |
| } |
| |
| foo() |
# Error 类型
- 事实上,JavaScript 已经给我们提供了一个 Error 类,我们可以直接创建这个类的对象:
- Error 包含三个属性:
- messsage:创建 Error 对象时传入的 message;
- name:Error 的名称,通常和类的名称一致;
- stack:整个 Error 的错误信息,包括函数的调用栈,当我们直接打印 Error 对象时,打印的就是 stack;
| function foo() { |
| const err = new Error("error~") |
| err.name = "ErrorMessage" |
| |
| throw err |
| } |
| |
| foo() |
| function foo() { |
| const err = new TypeError("TypeError~") |
| err.stack = 1 |
| throw err |
| console.log("foo函数后续的代码不会执行!") |
| } |
| |
| foo() |
-
Error 有一些自己的子类:
-
RangeError:下标值越界时使用的错误类型;
-
SyntaxError:解析语法错误时使用的错误类型;
-
TypeError:出现类型错误时,使用的错误类型;
# 异常的处理
- 我们会发现在之前的代码中,一个函数抛出了异常,调用它的时候程序会被强制终止:
- 这是因为如果我们在调用一个函数时,这个函数抛出了异常,但是我们并没有对这个异常进行处理,那么这个异常会继续传递到上一个函数调用中;
- 而如果到了最顶层(全局)的代码中依然没有对这个异常的处理代码,这个时候就会报错并且终止程序的运行;
- 我们先来看一下这段代码的异常传递过程:
| function foo() { |
| throw new Error('foo err message~') |
| } |
| |
| function bar() { |
| foo() |
| } |
| |
| function test() { |
| bar() |
| } |
| |
| function demo() { |
| test() |
| console.log('demo~') |
| } |
| |
| demo() |
- foo 函数在被执行时会抛出异常,也就是我们的 bar 函数会拿到这个异常;
- 但是 bar 函数并没有对这个异常进行处理,那么这个异常就会被继续传递到调用 bar 函数的函数,也就是 test 函数;
- 但是 test 函数依然没有处理,就会继续传递到我们的全局代码逻辑中;
- 依然没有被处理,这个时候程序会终止执行,后续代码都不会再执行了;
# 使用 try catch 来捕获异常
| function foo(type) { |
| if (type === 0) { |
| throw new Error("foo error message~") |
| } |
| } |
| |
| function bar() { |
| try { |
| foo(0) |
| console.log("bar函数后续的继续运行") |
| } catch(err) { |
| console.log("err:", err.message) |
| alert(err.message) |
| } finally { |
| console.log("finally代码执行~") |
| } |
| } |
| |
| function test() { |
| try { |
| bar() |
| } catch (error) { |
| console.log("error:", error) |
| } |
| } |
| |
| function demo() { |
| test() |
| } |
| |
| try { |
| demo() |
| } catch (err) { |
| console.log(err) |
| } |