1.基本知识

1. 错误对象

Error,SyntaxError,RangeError, ReferenceError,TypeError,URIError

上面的都是构造函数;

new 命令可以生成错误实例对象;可以传入描述作为参数,成为实例对象的message属性;

除了message属性,还有两个非标准属性(name, stack)stack是调用栈

var err = new Error("错误实例");
err.message; // "错误实例"
err.name; //"Error"
err.stack;//"Error: 错误实例 at <anonymous>:1:11"

2. throw语句

throw语句,如果不进行捕获(try...catch...),会中断当前script脚本中throw之后的所有代码执行。

<script>
    function test(){
        console.log('1');
        setTimeout(() => console.log('2')); //异步任务,下一轮执行,相当于最后执行
        throw new Error("err"); //未捕获,这个script内的后面的代码都不执行
        setTimeout(() => console.log('3')); // throw后
        console.log('4'); // throw后
    };
    function a() { console.log('5') }
    test();
    a(); //throw后
</script>
<script>
    function b() { console.log('6') }
    b(); // 另一个脚本
</script>
// 运行结果如下:
1
Error: err
6
2

如果在定时器中抛出异常,不会中断定时器之外的代码执行。定时器回调函数相当于自己一个“进程”。

示例: 将上面的未捕获异常放在setTimeout中

<script>
    function test(){
        console.log('1');
        setTimeout(() => console.log('2'));
        setTimeout(() => {throw new Error("err")}); //改为异步后,只影响本身
        setTimeout(() => console.log('3'));
        console.log('4');
    };
    function a() { console.log('5') }
    test();
    a();
</script>
<script>
    function b() { console.log('6') }
    b();
</script>
//运行结果如下
1
4
5
6
2
Uncaught Error: err
3

throw命令可以抛出任何类型的值;抛出什么,则捕获的就是什么!

try{
    throw "error"
} catch(err){
    console.log(err); //"error"
}

3.try...catch...finally..语句

使用try...catch...语句后,可以捕获错误,防止代码崩溃;

1)js中,程序执行遇到return, throw后,后面的语句不再执行;

try{
    throw "this is a error";
    console.log("after throw"); // 永远不会执行
} catch(error) {
    console.log(error);
}
// 运行结果
"this is a error"

2)浏览器中单独的try代码块中不能使用return;否则报错;而且catch无法捕获

try{
    return "this is a error";
} catch {
}
// Uncaught SyntaxError: return not in a function

由上面可以知道,return语句必须用在function中。另外,yield语句也是必须在Generator函数中被调用。

如果想在try/catch/finally代码块中使用return语句,可以在外面包裹一层function。

3)catch语句

如果try代码块中代码本身不抛出异常,也没有手动抛出异常,程序永远不会进入catch代码块。

try {
   console.log("throw nothind");
} catch { // 参数可以省略
   console.log("永远不会执行"); // try没有抛出错误,不会进入catch;永远不会被打印,
}

如果try代码块中抛出异常,则代码进入catch代码块执行完后,继续原来的代码执行。

try {
    throw "error";
 } catch { // 参数可以省略
    console.log("catch")
 }
 console.log('after');
 // 运行结果如下:
catch
after

4)finally语句

finally语句不论是否抛出异常,都会执行。且try后者catch中的return语句取值会在finally之前取值。

var count = 1;
function test() {
    try {
        console.log("try");
        throw new Error("this is a error");
    } catch(err) {
        console.log("catch error");
        return count;
    } finally {
        console.log("finally")
        count+=1;
    }
    console.log("after"); //永远不会执行
}
console.log(test()); 
// 运行结果如下
try catch error finally 1 //最后返回1,说明return在finally执行前先执行,但是最后才返回

如果在该代码块有return语句,会覆盖try,catch中的return语句

var count = 1;
function test() {
    try {
        console.log("try");
        throw new Error("this is a error");
    } catch(err) {
        console.log("catch error");
        return count;
    } finally {
        console.log("finally")
        count+=1;
        return count;
    }
    console.log("after"); //永远不会执行,因为前面有return语句
}
console.log(test());
//  运行结果如下
try
catch error
finally
2 //执行的是finally语句中的return语句

如果在该代码块中有return语句,会覆盖catch中的throw语句;

var count = 1;
function test() {
    try {
        throw new Error("this is a error");
    } catch(err) {
        console.log("catch error");
        throw err; // 不会执行;正常catch中遇到throw/return进入finally,等执行完finally代码块,返回这里抛出异常
    } finally {
        return count; // return 后不会返回catch代码块;如果没有return,会返回catch模块继续抛出异常,然后被外部的try...catch捕获
    }
}
try {
    test();
} catch(err) {
    console.log("catch test error"); // 不会执行
}
// 运行结果如下:
catch error
1 //返回1

4. finally语句应用

示例: 操作文件时,打开文件写入,不管是否写入成功,都要关闭文件

// 伪代码如下
openFile();
try {
    writeFile()
} catch(err) {
    console.log("写入失败");
} finally {
    closeFile(); // 总要执行
}

2. 实践应用

当使用接口请求服务器数据时,一般都要使用try...catch...方法,预防接口报错,程序崩溃!

03-26 12:24