ECMAS:异常捕获处理

ECMAS:异常捕获处理

在JS中,一旦出现某个错误,接下来的JS代码都会停止执行,这样就显的代码非常的不健壮。如果对异常进行捕获处理,那么接下来的JS代码会继续执行。

JS 异常捕获机制

try catch

try {
    console.log(app) // app 未定义
} catch (error) {
    // 
}

把不稳定代码放在 try 语句中。只要有一行代码出现问题,整个程序的执行流程就会立即调到 catch 语句中执行,而且这行出错代码后面的try中的其他语句都不会再执行。

在执行catch中的代码之前,JS引擎会首先根据错误类型自动创建一个错误,并通过catch后面的参数传递到catch中。不同的浏览器创建的error对象不一样,但是同创他们都包含一个message属性,值是这个错误的一些信息。

catch中的代码执行完毕之后,会继续执行后面的代码,程序不会停止下来。

finally

try {
    console.log(app) // app 未定义
} catch (error) {
    // 
} finally {
    // 
}

在 try…catch 中,try 中一旦出现错误则其他语句不能执行,如果不出现错误则 catch 中的语句不会执行。JS参考其他编程语言,也提供了一种 finally 语句:不管 try 中的语句有没有错误,在最后都会执行 finally 中的语句。

需要注意的是:

在js中,如果添加了 finally 语句,则 catch 语句可以省略。但是没有 catch 语句,则一旦发生错误就无法捕获这个错误,所以在执行完 finally 中的语句后,程序就会立即停止了。 所以,在实际使用中,最好一直带着 catch 语句。

throw 语句

throw语句用来抛出一个用户自定义的异常。当前函数的执行将被停止(throw之后的语句将不会执行),并且控制将被传递到调用堆栈中的第一个catch块。如果调用者函数中没有catch块,程序将会终止。

语法

throw expression;

使用throw语句来抛出一个异常。当你抛出异常时,expression 指定了异常的内容。

抛出一个对象

你可以在抛出异常时指定一个对象。然后可以在catch块中引用对象的属性。以下示例创建一个类型为UserException的对象,并在throw语句中使用它。

function UserException(message) {
   this.message = message;
   this.name = "UserException";
}
function getMonthName(mo) {
   mo = mo-1; // 调整月份数字到数组索引 (1=Jan, 12=Dec)
   var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
      "Aug", "Sep", "Oct", "Nov", "Dec"];
   if (months[mo] !== undefined) {
      return months[mo];
   } else {
      throw new UserException("InvalidMonthNo");
   }
}

try {
   // statements to try
   var myMonth = 15; // 15 超出边界并引发异常
   var monthName = getMonthName(myMonth);
} catch (e) {
   var monthName = "unknown";
   console.log(e.message, e.name); // 传递异常对象到错误处理
}

在设计复杂程序时,需要对异常进行分类识别,这会变得非常有用。

重新抛出异常

你可以使用throw来抛出异常。下面的例子捕捉了一个异常值为数字的异常,并在其值大于50后重新抛出异常。重新抛出的异常传播到闭包函数或顶层,以便用户看到它。

  try {
     throw 100; // 抛出一个数值异常
  } catch (e) {
     if (e <= 50) {
        // 异常在 1-50 之间时,直接处理
     } else {
        // 异常无法处理,重新抛出
        throw e;
     }
  }
  // Uncaught 100

Error 构造器

详细使用方法请参考 MDN Error 文档,这里不做赘述。

通过Error构造器可以创建一个错误对象,您可以抛出它并捕获,更牛逼的是您可以将它作为自定义异常的基础对象

常用的属性

  • Error.prototype.message 错误描述
  • Error.prototype.name error类型的名称,初始值为"Error"
  • Error.prototype.toString()

toString() 方法返回一个指定的错误对象(Error object)的字符串表示:

Error.prototype.toString = function()
{
  "use strict";

  var obj = Object(this);
  if (obj !== this)
    throw new TypeError();

  var name = this.name;
  name = (name === undefined) ? "Error" : String(name);

  var msg = this.message;
  msg = (msg === undefined) ? "" : String(msg);

  if (name === "")
    return msg;
  if (msg === "")
    return name;

  return name + ": " + msg;
};

demo 演示

try {
  var e = new Error("error msg");
  e.name = "ParseError";
  throw e;
} catch (e) {
  console.log(typeof e); // object
  console.log(e.name); // ParseError
  console.log(e.message); // error msg
  console.log(e); // Error: error msg \n at index.html:18
  console.log(JSON.stringify(e)) // {"name":"ParseError"}, message 属性挂载在Error.prototype上的
}
var e = new Error("fatal error");
print(e.toString()); // "Error: fatal error"

e.name = undefined;
print(e.toString()); // "Error: fatal error"

e.name = "";
print(e.toString()); // "fatal error"

e.message = undefined;
print(e.toString()); // "Error"

e.name = "hello";
print(e.toString()); // "hello"

错误类型

所有的JS内置的错误类型都继承自 Error。

1303135-20190120001121531-1933257009.png

上图中 EvalError 继承了 Error,并且 EvalError.prototype.name = 'EvalError',其他错误类型也类似。

EvalError

创建一个error实例,表示错误的原因:与 eval() 有关。

InternalError

创建一个代表Javascript引擎内部错误的异常抛出的实例。 如: "递归太多".

RangeError

创建一个error实例,表示错误的原因:数值变量或参数超出其有效范围。

ReferenceError

创建一个error实例,表示错误的原因:无效引用。

SyntaxError

创建一个error实例,表示错误的原因:eval()在解析代码的过程中发生的语法错误。

TypeError

创建一个error实例,表示错误的原因:变量或参数不属于有效类型。

URIError

创建一个error实例,表示错误的原因:给 encodeURI()或 decodeURl()传递的参数无效。

参考文档

  1. MDN Error
  2. MDN Errors

转载于:https://www.cnblogs.com/gaollard/p/10247037.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值