throw
看下列代码:
function add(num1, num2) {
if (typeof num1 !== "number" || typeof num2 !== "number") {
return;
}
return num1 + num2;
}
add(10,20)
add(10,"111")
在上面代码中,我们希望add函数接收的参数为数字类型,如果不是数字类型那么就不继续执行函数,所以采用了return来终止函数的执行。但是,在js中,如果直接return其实是有返回值的,返回值是undefined的,而且我们希望告诉函数使用者,为什么返回了个undefined,想传递一些错误信息给使用者,比如错误位置、调用栈信息等,单纯使用return来返回这些信息是比较难做到的。所以有了throw语句,通过throw来抛出一个异常。
function add(num1, num2) {
if (typeof num1 !== "number" || typeof num2 !== "number") {
throw "params type error";
}
return num1 + num2;
}
add(10,20)
add(10,"111")
这样,我们浏览器就会抛出一个错误:
throw后面可以跟基本数据类型,如string、number等,也可以跟一个对象,而对象可以让我们记录更多的错误信息。
Error
Error是一个构造函数,可以帮我们生成一个错误对象。我们可以配合throw这样使用:
function foo(){
throw new Error("error 123")
}
foo()
这样就会帮我们抛出一个错误对象。这个错误对象包含三个属性:
- messsage:创建Error对象时传入的message;
- name:Error的名称,通常和类的名称一致;
- stack:整个Error的错误信息,包括函数的调用栈,当我们直接打印Error对象时,打印的就是stack
Error作为一个类,还有自己的子类:
- RangeError:下标值越界时使用的错误类型;
- SyntaxError:解析语法错误时使用的错误类型;
- TypeError:出现类型错误时,使用的错误类型;
try catch 异常处理
在上面我们使用throw的时候会发现,一旦执行到throw抛出异常后,我们后面所有的代码都将不会被执行,但在实际应用中,我们是不希望这样的,就算抛出异常,我们依然希望别的代码继续执行。这时我们就需要用try catch来捕获这个错误并进行处理了:
function foo() {
throw new Error("error 123");
}
function bar() {
try {
foo();
} catch (err) {
console.log("处理错误");
}
}
bar();
console.log("bar函数后的代码");
执行上面代码,最后打印:
我们可以发现,即使bar内的foo函数抛出异常后代码也照常执行。
这里注意一下,对于抛出错误,在js中是一直往上一层进行抛出的。比如上面代码,当foo函数throw过后抛出了异常,如果在foo内没有捕获,那么就会将这个错误抛出到调用foo函数的bar函数,如果bar函数我们没有捕获这个错误进行处理那么就会继续往上抛,直到最顶层都还没有对这个错误进行捕获处理,那么这时就会抛出错误并停止程序运行。
在最后还有一个finally方法,finally内的代码块是无论是否抛出异常都会执行,一般在这里做一些代码的收尾工作:
function foo() {
throw new Error("error 123");
}
function bar() {
try {
foo();
} catch (err) {
console.log("处理错误");
} finally{
console.log("finally")
}
}
bar();
注意:如果try和finally中都有返回值,那么会使用finally当中的返回值
function foo() {
return 11;
}
function bar() {
try {
return foo();
} catch (err) {
console.log("处理错误:", err);
} finally {
return 20;
}
}
console.log(bar());//20
在es10中,catch可以不用跟一个参数进行使用,即可以这样:
try{
...
}catch{
...
}