点此查看 所有教程、项目、源码导航
文章目录
- [1. 背景](#1. 背景)
- [2. throw 抛出异常](#2. throw 抛出异常)
-
- [2.1 throw 的作用](#2.1 throw 的作用)
- [2.2 基础示例](#2.2 基础示例)
- [2.3 什么时候需要 throw](#2.3 什么时候需要 throw)
- [3. JS 内置错误类型](#3. JS 内置错误类型)
-
- [3.1 Error](#3.1 Error)
- [3.2 ReferenceError 引用错误](#3.2 ReferenceError 引用错误)
- [3.3 TypeError 类型错误](#3.3 TypeError 类型错误)
- [3.4 RangeError 范围错误](#3.4 RangeError 范围错误)
- [4. 异常处理常见坑](#4. 异常处理常见坑)
-
- [4.1 不要无脑捕获所有异常](#4.1 不要无脑捕获所有异常)
- [4.2 异常尽量就近捕获](#4.2 异常尽量就近捕获)
- [4.3 区分:哪些错误抓不住](#4.3 区分:哪些错误抓不住)
- [5. 综合小案例](#5. 综合小案例)
- [6. 小结](#6. 小结)
1. 背景
上一篇我们学习了 try catch finally,用来捕获代码运行时自动产生的异常。
异常不只有 JS 引擎自动抛出这一种情况,在开发中,很多时候是我们自己判断业务逻辑,觉得当前数据不合法,需要主动抛出错误,提醒调用者。
本篇我们学习 throw 主动抛出异常,同时认识 JS 内置的几种错误类型,以及异常处理的编码规范。
2. throw 抛出异常
2.1 throw 的作用
throw 关键字可以让我们手动制造一个异常 。
一旦执行 throw,代码立刻中断,抛出的内容会被外层的 catch 捕获。
基础语法:
js
throw 内容;
开发规范:尽量抛出错误对象,而不是直接抛出字符串、数字。
2.2 基础示例
js
var age = 15;
if (age < 18) {
throw new Error("年龄不足18岁,不允许访问");
}
console.log("验证通过");
直接运行这段代码,控制台会报错,后面的 console.log 不会执行。
如果外层包上 try-catch,就可以接住我们手动抛出的异常:
js
var age = 15;
try {
if (age < 18) {
throw new Error("年龄不足18岁,不允许访问");
}
console.log("验证通过");
} catch (err) {
console.log("捕获到自定义错误:", err.message);
}
2.3 什么时候需要 throw
当函数收到不符合预期的参数、条件不满足时,适合使用 throw。
函数只负责校验规则,出错的时候抛出异常,由调用方决定怎么处理这个错误。
js
function getScore(score) {
if (score < 0 || score > 100) {
throw new Error("分数必须在0~100之间");
}
return score;
}
try {
getScore(120);
} catch (err) {
console.log(err.message);
}
3. JS 内置错误类型
我们前面一直用 new Error(),这是通用错误。
JS 还内置了几类细分的错误构造函数,用来区分不同种类的问题。
3.1 Error
通用错误类型,其他错误类型都继承自它。
不确定具体错误类型的时候,优先使用它。
js
throw new Error("通用错误提示");
3.2 ReferenceError 引用错误
访问一个没有定义的变量时,引擎抛出的就是这个类型。
我们自己抛的时候,适合标记 "找不到变量 / 标识" 这类场景。
js
throw new ReferenceError("该变量不存在");
3.3 TypeError 类型错误
变量的类型不符合预期,就适合用这个。
比如期待是数字,传进来却是字符串;期待是函数,传进来是对象。
js
var num = "abc";
if (typeof num !== "number") {
throw new TypeError("参数必须是数字类型");
}
3.4 RangeError 范围错误
数值超出合法范围时使用。
js
function setCount(n) {
if (n < 0) {
throw new RangeError("数量不能是负数");
}
}
补充:还有 SyntaxError 语法错误,这个是解析阶段产生的,代码没执行完就报错,try-catch 无法捕获,我们一般不会手动 throw 这个类型。
4. 异常处理常见坑
4.1 不要无脑捕获所有异常
不要为了程序不报错,随便给一大段代码套上 try-catch。
js
// 不推荐
try {
// 一大段很多逻辑
} catch (e) {}
空 catch 会悄悄吃掉所有错误,代码出问题的时候没有任何提示,调试非常困难。
4.2 异常尽量就近捕获
哪里容易出错,就在哪里加 try-catch,不要所有错误都堆在最外层统一捕获,不利于定位问题。
4.3 区分:哪些错误抓不住
语法错误(少写括号、少写分号、关键字写错)属于解析阶段错误,JS 还没开始执行代码,try-catch 不起作用。
try-catch 只能捕获运行时抛出的异常,包括引擎自动抛出、我们 throw 手动抛出的。
5. 综合小案例
结合 throw + try-catch + TypeError 写一个参数校验的示例:
js
function calcArea(width, height) {
if (typeof width !== "number" || typeof height !== "number") {
throw new TypeError("宽和高必须是数字");
}
if (width <= 0 || height <= 0) {
throw new RangeError("宽高必须大于0");
}
return width * height;
}
try {
var res = calcArea(-10, 20);
console.log("面积:", res);
} catch (err) {
console.log("错误类型:", err.name);
console.log("错误信息:", err.message);
}
6. 小结
throw用来主动抛出异常,中断代码执行,配合 try-catch 实现自定义错误提示;- 推荐抛出错误对象
new Error(),不建议直接抛出字符串; - 内置错误:Error、ReferenceError、TypeError、RangeError,不同场景选择对应的类型;
- 编码原则:不滥用 try-catch、禁止空 catch 吞掉错误、语法错误无法被捕获。