JavaScript错误处理-学习笔记

在这里插入图片描述

1 Error及其派生对象

1.1 Error对象

JavaScript在解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript原生提供了Error构造函数,所抛出的错误都是Error构造函数的实例。

var err=new Error('出错了');
err.message //"出错了"

以上示例中,参数为message属性,这个参数是必须的。除此之外,还提供了name(错误名称)属性和stack(错误的堆栈)属性,但这两个属性是非标准的,不是每种实现都有。

1.2 Error派生对象

Error实例对象是最一般的错误类型,在此基础上JavaScript还定义了6种错误类型:

  1. SyntaxError:解析代码时的语法错误

  2. ReferenceError引用一个不存在的变量时发生的错误。

  3. RangeError:一个值超出有效范围时发生的错误。

  4. TypeError:变量或参数不是预期类型时发生的错误。

  5. URIErrorURI 相关函数的参数不正确时抛出的错误。主要涉及encodeURI()decodeURI()encodeURIComponent()decodeURIComponent()escape()unescape()这六个函数。

  6. EvalErroreval函数没有被正确执行时抛出的错误。

针对以上6种派生对象,我们都可以通过new关键字手动生成错误对象的实例。同样地,message也是必要参数。

2 自定义错误

除了以上的原生提供的错误对象,我们还可以自定义错误对象。代码实现如下:

function MyError(message){
	this.message="...";
    this.name="...";
}

MyError.prototype=new Error();
MyError.prototype.constructor=MyError;

然后我们就可以通过new关键字来新建自定错误对象了。

3 错误处理

  1. throw语句:手动中断程序执行,抛出一个错误(自定义错误也可以)。

  2. try...catch结构:try代码块中的错误会被catch代码块捕获处理。如果不确定某些代码是否会报错,就可以把它们放在try...catch代码块之中。

    举个例子:

    注:catch代码块之中,还可以再抛出错误,甚至使用嵌套的try...catch结构。

    try {
      throw "出错了";
    } catch (e) {
      console.log(111);
    }
    console.log(222);
    

    输出结果为:

    111
    222
    

    分析:从运行结果看,程序没有中断执行,并且继续向下执行完毕。

    另外为了捕获不同类型的错误,从而进行不同的处理,也可以在catch块中加入判断语句:

    try {
      //...
    } catch (e) {
      if (e instanceof EvalError) {
        console.log(e.name + ": " + e.message);
      } else if (e instanceof RangeError) {
        console.log(e.name + ": " + e.message);
      }
      // ...
    }
    
  3. finally代码块:try...catch结构允许在最后添加一个finally代码块,表示不管是否出现错误,都必需在最后运行的语句。

    • 来看一个典型的应用场景:首先打开一个文件,然后在try代码块中写入文件,如果没有发生错误,则运行finally代码块关闭文件;一旦发生错误,则先使用catch代码块处理错误,再使用finally代码块关闭文件。

      openFile();
      
      try {
        writeFile(Data);
      } catch(e) {
        handleError(e);
      } finally {
        closeFile();
      }
      
    • 再举个例子:没有catch块,try块中有抛出错误。

      function cleansUp() {
        try {
          throw new Error('出错了……');
          console.log('此行不会执行');
        } finally {
          console.log('完成清理工作');
        }
      }
      
      cleansUp()
      

      运行结果如下:显然,在中断执行前首先执行了finally块,然后再抛出的错误信息。

      完成清理工作
      Uncaught Error: 出错了……
          at cleansUp (<anonymous>:3:11)
          at <anonymous>:10:1
      
    • 再来看一个例子:分析一下return语句与finally块的执行顺序。

      var count = 0;
      function countUp() {
        try {
          return count;
        } finally {
          ++count;
        }
      }
      
      countUp() //0
      count //1
      

      分析:虽然try块中有return语句,但还是运行了finally代码块,而且return语句执行是在finally块之前的,只是等finally块执行完毕后才返回的。

  4. try...catch...finally结构:

    • 直接举个例子来看这三者之间的执行顺序:

      function f() {
        try {
          console.log(0);
          throw 'bug';
        } catch(e) {
          console.log(1);
          return true; // 这句原本会延迟到 finally 代码块结束再执行
          console.log(2); // 不会运行
        } finally {
          console.log(3);
          return false; // 这句会覆盖掉前面那句 return
          console.log(4); // 不会运行
        }
      
        console.log(5); // 不会运行
      }
      
      var result=f();
      //0
      //1
      //3
      
      result //false
      

      从运行结果看:catch代码块结束执行之前,一遇到return语句,就会先执行finally代码块,由于return false语句,因此就直接返回了,不再会回去执行catch代码块剩下的部分了。

    • 再举个例子:catch块中有throw语句,如下例子所示:

      function f() {
        try {
          throw '出错了!';
        } catch(e) {
          console.log('捕捉到内部错误');
          throw e; // 这句原本会等到finally结束再执行
        } finally {
          return false; // 直接返回
        }
      }
      
      f()
      

      运行结果为:

      捕捉到内部错误
      

      分析:进入catch代码块之后,一遇到throw语句,就会去执行finally代码块,其中有return false语句,因此就直接返回了,不再会回去执行catch代码块剩下的部分了。

    总结:throw语句和return语句都会触发finally块的执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值