毛病检测(1)------try-catch语句 From 《高程3》

0 媒介

现在读到了《高程3》的毛病检测部份,现在先挖一个坑,关于毛病检测应当写三篇总结:firebug检测毛病和输出信息;try-catch毛病捕捉;罕见毛病品种。

本篇逻辑思绪以下:起首引见举行毛病捕捉的try-catch语句;然后引见罕见的毛病范例,这点会连系firebug来申明;其次引见try-catch语句和毛病范例连系运用以捕捉毛病;然则假如捕捉的毛病以浏览器的言语示意,照样很难找到毛病,因此引荐运用throw抛出开发者自定义的毛病,如许,毛病的位置和缘由就会更轻易发明;末了就毛病抛出和毛病捕捉举行了总结议论。

1 try-catch简介

优越的毛病处置惩罚机制可以让用户和开发者实时获得提示,晓得究竟发作了什么事,因此不会手足无措。ECMA-262 第 3 版引入了 try-catch 语句,作为 JavaScript 中处置惩罚异常的一种规范体式格局。基础的语法以下所示,

try{
// 能够会致使毛病的代码
} catch(error){
// 在毛病发作时怎样处置惩罚
}

我们应当把一切能够会抛出毛病的代码都放在 try 语句块中,而把那些用于毛病处置惩罚的代码放在 catch 块中。假如 try 块中的任何代码发作了毛病,就会马上退出代码实行历程,然后接着实行 catch 块。此时, catch 块会吸收到一个包括毛病信息的对象。纵然你不想运用这个毛病对象,也要指定一个参数名。这个对象中包括的现实信息会因浏览器而异,但配合的是有一个保存着毛病音讯的 message 属性。这个 message 属性是唯一一个可以保证一切浏览器都支撑的属性,除此以外, IE、 Firefox、 Safari、 Chrome 以及 Opera 都为毛病对象增加了其他相干信息。在跨浏览器编程时,最好照样只运用 message 属性。
一个测试例子:
《毛病检测(1)------try-catch语句 From 《高程3》》

只需代码中包括 finally 子句,则不管 try 或 catch 语句块中包括什么代码——以至 return 语句,都不会阻挠 finally 子句的实行。以下例所示:

function testFinally() {
  try {
    return 2;
  } catch (error) {
    return 1;
  } finally {
    return 0;
  }
}
function testWithoutFinally() {
  try {
    return 2;
  } catch (error) {
    return 1;
  }
}
console.log(testFinally());//输出0
console.log(testWithoutFinally());//输出2

假如供应 finally 子句,则 catch 子句就成了可选的(catch 或 finally 有一个即可)。 IE7 及更早版本中有一个 bug:除非有 catch 子句,不然 finally 中的代码永久不会实行。IE8 修复了这个 bug。假如你依然要斟酌 IE 的初期版本,那就只好供应一个 catch 子句,哪怕内里什么都不写。

另一个测试实例:

var example = function() {
  try {
    window.someNonexistentFunction();
  } catch (error) {
    console.log(error.name);
    console.log(error.message);
    return 1;
  } finally {
    console.log('everything is over');
  }
};
example();

测试效果:前后实行了try/catch/finally中的语句,题目是为何会在末了实行一次catch中的return语句?留给本身一个题目吧。
《毛病检测(1)------try-catch语句 From 《高程3》》

2 毛病范例

每种毛病都有对应的毛病范例,而当毛病发作时,就会抛出响应范例的毛病对象(error object)。ECMA-262 定义了以下 7 种毛病范例:

1) Error 是基范例,其他毛病范例都继承自该范例。因此,一切毛病范例同享了一组雷同的属性(毛病对象中的要领满是默许的对象要领)。
2)EvalError 范例的毛病会在运用 eval()函数而发作异常时被抛出,然则抛出的毛病不一定是EvalError 范例。假如没有把 eval()当做函数挪用,Firefox 4+和 IE8 对此抛出 TypeError。

3)RangeError 范例的毛病会在数值超越响应局限时触发。比方,在定义数组时,假如指定了数组不支撑的项数(如-20 或 Number.MAX_VALUE),就会触发这类毛病。

4)在找不到对象的状况下,会发作 ReferenceError(这类状况下,会直接致使人所共知的”object expected”浏览器毛病)。一般,在接见不存在的变量时,就会发作这类毛病。

5) 至于 SyntaxError,当我们把语法毛病的 JavaScript 字符串传入 eval()函数时,就会致使此类毛病。假如语法毛病的代码涌现在 eval()函数以外,则不太能够运用 SyntaxError,因为此时的语法毛病会致使 JavaScript 代码马上住手实行。

6)TypeError 范例在 JavaScript 中会常常用到,在变量中保存着不测的范例时,或许在接见不存在的要领时,都邑致使这类毛病。毛病的缘由虽然多种多样,但归根结柢照样因为在实行特定于范例的操纵时,变量的范例并不符合请求而至。最常发作范例毛病的状况,就是传递给函数的参数事前未经搜检,效果传入范例与预期范例不符合。

7) 在运用 encodeURI()或 decodeURI(),而 URI 花样不正确时,就会致使 URIError 毛病。这类毛病也很少见,因为前面说的这两个函数的容错性异常高。

上述测试历程在FF以下:

《毛病检测(1)------try-catch语句 From 《高程3》》

3 运用try-catch语句捕捉毛病

要想晓得毛病的范例,可以像下面如许在 try-catch 语句的 catch 语句中运用 instanceof 操纵符。

try {
  someFunction();
} catch (error){
  if (error instanceof TypeError){
//处置惩罚范例毛病
} else if (error instanceof ReferenceError){
//处置惩罚援用毛病
} else {
//处置惩罚其他范例的毛病
}
}

在跨浏览器编程中,搜检毛病范例是肯定处置惩罚体式格局的最轻便门路;而包括在 message 属性中的毛病音讯会因浏览器而异。
运用 try-catch 最适合处置惩罚那些我们无法控制的毛病。假定你在运用一个大型 JavaScript 库中的函数,该函数能够会有意无意地抛出一些毛病。因为我们不能修正这个库的源代码,所以大可将对该函数的挪用放在 try-catch 语句当中,万一有什么毛病发作,也好适当地处置惩罚它们。

4 throw抛出自定义毛病

与 try-catch 语句相配的另有一个 throw 操纵符,用于随时抛出自定义毛病。抛出毛病时,必需要给 throw 操纵符指定一个值,这个值是什么范例,没有请求。在碰到 throw 操纵符时,代码会马上住手实行。仅当有 try-catch 语句捕捉到被抛出的值时,代码才会继承实行。

经由过程运用自定义的内置毛病范例,可以更真实地模仿浏览器毛病。每种毛病范例的组织函数吸收一个参数,即现实的毛病音讯。下面是例子。

throw new Error("Something bad happened.");
throw new SyntaxError("I don’t like your syntax.");
throw new TypeError("What type of variable do you take me for?");
throw new RangeError("Sorry, you just don’t have the range.");
throw new EvalError("That doesn’t evaluate.");
throw new URIError("Uri, is that you?");
throw new ReferenceError("You didn’t cite your references properly.");

浏览器会像处置惩罚本身天生的毛病一样,来处置惩罚这些代码抛出的毛病。换句话说,浏览器会以通例体式格局报告这一毛病,并且会显现这里的自定义毛病音讯。

抛出自定义毛病的意义:轻易疾速定位毛病并纠错。虽然浏览器会本身报错,然则这些报错信息在浏览器中达不到一致,而且假如涌现同品种型毛病,查找泉源是庞杂的,尤其是在数千行代码中。然则假如你晓得能够的代码毛病,可以直接在代码中增加这些自定义的毛病,一旦发作这些毛病,浏览器就报出自定义毛病,关键是这个毛病的位置和范例不言而喻。
实例:一个必需吸收数组作为参数的函数假如吸收字符串作为参数就会报错。

function process(values){
    values.sort();
    for (var i=0, len=values.length; i < len; i++){
        if (values[i] > 100){
            return values[i];
        }
    }
    return -1;
}
var a = process("string");
 console.log(a);

firebug中效果:
《毛病检测(1)------try-catch语句 From 《高程3》》
增加自定义毛病后的代码:

function process(values){
  if (!(values instanceof Array)){
    throw new Error("process(): Argument must be an array.");
  }
    values.sort();
    for (var i=0, len=values.length; i < len; i++){
        if (values[i] > 100){
            return values[i];
        }
    }
    return -1;
    }

var a = process("string");
 console.log(a);

firebug中效果:
《毛病检测(1)------try-catch语句 From 《高程3》》

假如 values 参数不是数组,就会抛出一个毛病。毛病音讯中包括了函数的称号,以及为何会发作毛病的明白形貌。假如一个庞杂的 Web 应用程序发作了这个毛病,那末查找题目标泉源也就轻易多了。

应用原型链还可以经由过程继承 Error 来建立自定义毛病范例。此时,需要为新建立的毛病范例指定 name 和 message 属性。
一个实例:

//经由过程继承Error完成自定义毛病范例,要定义name和message属性
   function CustomError(message){       
       this.name = "CustomError";
       this.message = message;
   }
   CustomError.prototype = new Error();

   function process(values){
       //假如涌现毛病,就抛出自定义毛病范例的对象实例
       if (!(values instanceof Array)){
           throw new CustomError("process(): Argument must be an array.");
       }
       values.sort();
       for (var i=0, len=values.length; i < len; i++){
           if (values[i] > 100){
               return values[i];
           }
       }
       return -1;
   }

   process("string");

firebug显现自定义范例的毛病:

《毛病检测(1)------try-catch语句 From 《高程3》》

5 抛出毛病与运用 try-catch捕捉毛病

关于什么时候该抛出毛病,而什么时候该运用 try-catch 来捕捉它们,是一个陈词滥调的题目。一般来说,应用程序架构的较低条理中常常会抛出毛病,但这个条理并不会影响当前实行的代码,因此毛病一般得不到真正的处置惩罚。假如你盘算编写一个要在许多应用程序中运用的 JavaScript 库,以至只编写一个能够会在应用程序内部多个处所运用的辅佐函数,我都强烈建议你在抛出毛病时供应详实的信息。然后,即可在应用程序中捕捉并适当地处置惩罚这些毛病。
说到抛出毛病与捕捉毛病,我们以为只应当捕捉那些你确实地晓得该怎样处置惩罚的毛病。捕捉毛病的目标在于防止浏览器以默许体式格局处置惩罚它们;而抛出毛病的目标在于供应毛病发作详细缘由的音讯。

    原文作者:zhangding
    原文地址: https://segmentfault.com/a/1190000007208203
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞