资讯专栏INFORMATION COLUMN

JavaScript 错误处理与调试——“错误处理”的注意要点

draveness / 2846人阅读

摘要:使用函数发生异常时抛出。数值超出相应范围时抛出。抛出错误与相配的还有一个操作符,用于抛出自定义错误。错误事件没有通过处理的错误都会触发对象的事件。任何浏览器中,事件处理程序都不会创建对象,但它可以接受个参数错误消息错误所在的和行号。

try-catch语句

该语句最适合处理那些我们无法控制的错误,在明明白白地知道自己的代码会发生错误时,再使用该语句就不太合适了。

ECMA-262第3版引入了try-catch语句,基本的语法如下所示:

try {
    // statements
} catch(e) {
    // statements
    console.log(e);
}

即使不使用这个错误对象,也要起个名字,对象中包含的实际信息因浏览器而异,但共同的是一个保存错误消息的

message属性,ECMA-262还规定了一个保存错误类型的

name属性

所有浏览器都支持这个属性(Opera 9之前的版本除外)。

try {
    document.getElementByIfd("fdsa");
} catch(e) {
    // statements
    console.log(e.message); //document.getElementByIfd is not a function
    console.log(e.name); //TypeError
}

又如:

try {
    var x = 1;
    var y = 0;
    console.log(z);
} catch(e) {
    // statements
    console.log(e.message); //z is not defined
    console.log(e.name); //ReferenceError
}
finally子句

虽然在try-catch块中是可选的,但finally子句一经用,无论如何都会执行,甚至return语句都不会阻止,例如:

function test() {
    try {
        return 1;
    } catch (error) {
        return 2;
    } finally {
        return 3;
    }
}

上述代码返回3,当try中代码正常执行,finally会执行;当try中代码出现错误,catch代码会执行,finally代码也会执行。

错误类型

每种错误都有对应的错误类型,而当错误发生时,就会抛出相应类型的错误对象,ECMA-262定义了7种错误类型:

* `Error`: 基类型。
* `EvalError`: 使用eval()函数发生异常时抛出。
* `RangeError`: 数值超出相应范围时抛出。
* `ReferenceError`: 找不到对象时抛出。
* `SyntaxError`: 使用eval()函数中的字符串有语法错误时抛出。
* `TypeError`: 在变量中保存意外类型或访问不存在的方法时抛出。
* `URIError`: 使用encodeURI或decodeURI()中URI格式不正确时抛出。
抛出错误

与try-catch相配的还有一个

throw操作符,用于抛出自定义错误。

抛出错误时,必须给throw操作符指定一个值,这个值的类型没有要求,例如:

throw 123;
throw "Hello World!";

在遇到throw操作符时,代码会立即停止执行。

通过使用某种内置错误类型,可以更真实

如:

try {
    throw new Error("nooo");
} catch (e) {
    console.log(e.message); //nooo
    console.log(e.name); //Error
}

或:

throw new SyntaxError("wwwwtttttfffff");

也可以创建自定义错误类型:

function CustomError (message) {
    this.name = "CustomError";
    this.message = message;
}
CustomError.prototype = new Error();
var somebug = new CustomError("wtf");

try {
    throw somebug
} catch(e) {
    console.log(e.name); //CustomError
    console.log(e.message); //wtf
}

捕获错误的目的在于避免浏览器以默认方式处理它们;而抛出错误的目的在于提供错误发生具体原因的消息。

错误(error)事件

没有通过try-catch处理的错误都会触发window对象的

error事件。任何浏览器中,onerror事件处理程序都不会创建event对象,但它可以接受3个参数:错误消息、错误所在的URL和行号。

只要发生错误,无论是不是浏览器生成的,都会触发error事件,并执行这个事件处理程序,如果在事件处理程序中返回false,可以阻止浏览器报告错误的默认行为,例如:

throw new Error("hello there");
window.onerror = function() {
    console.log(message); //Uncaught Error: hello there
    return false;
}

图像也支持error事件,只要图像的src属性中的URL不能返回可以被识别的图像格式,就会触发error事件。

var x = new Image();
x.onerror = function () {
    console.log("message"); //message
};
x.src = "fds.png";
常见的错误类型

常见的三种错误类型为:

类型转换错误

数据类型错误

通信错误

类型转换错误

类型转换错误常发生在使用某个操作符或者自动转换数据类型的场景

第一种常见错误是使用相等和不等操作符

console.log(1 == "1"); //true
console.log(1 == true); //true

改进: 推荐使用全等( === ) 和非全等( !== ) 操作符, 来避免发生因为使用相等和不等操作符时引发的类型转换错误;

console.log(1 === "1"); //false
console.log(1 === true); //false

第二种常见错误是在流控制语句中使用非布尔值.

function concat(str1, str2) {
    if (str2) {
        return str1 + str2;
    } else {
        return str1;
    }
}
concat("a", 0); //a"
concat("a", 1); //"a1"

该方法的目的是当第二个参数存在的时候返回两个字符串拼接结果;

当第二个参数不存在的时候直接返回第一个参数.可是除了undefined会转换为布尔值false外, 0 也会转换为false, 而1则转换为true.因此调用结果与本意不太一致.

改进:

function concat(str1, str2) {
    if (typeof str2 == "string") {
        return str1 + str2;
    } else {
        return str1;
    }
}
concat("a", 0); //a"
concat("a", 1); //"a"
数据类型错误

在JavaScript中, 使用变量和函数参数之前是不会自动进行类型检验的.因此需要开发人员自己编写数据类型检测的代码.例如:

function reverseSort(values) {
    if (values) { //这里的判断不能保证是数组类型
        values.sort();
        values.reverse();
    }

    console.log(values);
}
reverseSort("a"); //TypeError

这里如果传入的参数不是数组类型, 就会发生数据类型错误.一般来说, 对于基本类型使用typeof进行类型检验, 对于对象类型使用instanceof进行类型检验.

function reverseSort(values) {
    if (values instanceof Array) {
        values.sort();
        values.reverse();
    }
    console.log(values);
}
reverseSort("a"); //a"
reverseSort([6, 2, 3, 8, 1, 5]); //[8, 6, 5, 3, 2, 1]
通信错误

场景一是在将数据发送给服务器之前, 未使用encodeURIComponent() 对数据进行编码.例如:

www.cnblogs.com ? backurl = http : //www.cnblogs.com?a=1

解决方法是使用encodeURIComponent() 对backurl后面的参数进行编码, 结果为:

www.cnblogs.com ? backurl = http % 3 A % 2 F % 2 Fwww.cnblogs.com % 3 Fa % 3 D1

场景二是对于查询字符串, 也要对于查询参数的名和值都进行编码.

把错误记录到服务器

如果把前后端的错误信息集中进行汇总记录, 能极大的方便对数据库错误日志的分析.要把JavaScrpt错误记录到服务器需要借助image控件进行, 因为所有浏览器都支持image对象, 而且可以避免跨域限制.

首先新建一个服务端页面用于处理错误数据.这个页面从查询字符串中获取错误数据, 然后将数据写入到错误日志中, 例如该页面为a.ashx.

然后在调用页面中, 创建image对象, 并且为其src属性赋值, 这样就可以将错误信息发送到服务端页面了.

function logError(msg) {
    var img = new Image();
    img.src = "a.ashx?msg=" + encodeURIComponent(msg);
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78683.html

相关文章

  • JavaScript 错误处理调试——“调试技术常见IE错误注意要点

    摘要:将消息记录到控制台和来说,可通过对象向控制台中写入消息。如常见的错误操作终止无效字符未找到成员未知运行时错误语法错误系统无法找到指定资源 将消息记录到控制台 console IE8、Firefox、Chrome和Safari来说,可通过console对象向JavaScript控制台中写入消息。对象有下列方法: error(message):将错误消息记录到控制台 info(messa...

    GT 评论0 收藏0
  • JavaScript错误正确处理方式,你用对了吗?

    摘要:单元测试会体现出以上错误处理程序的作用如果出现问题,错误处理程序就会返回。同时错误会展开堆栈,这对调试非常有帮助。展开堆栈处理异常的一种方式是在调用堆栈的顶部加入。确保你的错误处理处在相同域中,这样会保留原始消息,堆栈和自定义错误对象。 JavaScript的事件驱动范式增添了丰富的语言,也是让使用JavaScript编程变得更加多样化。如果将浏览器设想为JavaScript的事件驱动...

    chaos_G 评论0 收藏0
  • JavaScript 编程精解 中文第三版 八、Bug 和错误

    摘要:幸运的是,使用符号创建的构造器,如果在不使用来调用,则始终会报错,即使在非严格模式下也不会产生问题。 来源:ApacheCN『JavaScript 编程精解 中文第三版』翻译项目原文:Bugs and Errors 译者:飞龙 协议:CC BY-NC-SA 4.0 自豪地采用谷歌翻译 部分参考了《JavaScript 编程精解(第 2 版)》 调试的难度是开始编写代码的两倍。 因此,如...

    wujl596 评论0 收藏0
  • 【全文】狼叔:如何正确学习Node.js

    摘要:感谢大神的免费的计算机编程类中文书籍收录并推荐地址,以后在仓库里更新地址,声音版全文狼叔如何正确的学习简介现在,越来越多的科技公司和开发者开始使用开发各种应用。 说明 2017-12-14 我发了一篇文章《没用过Node.js,就别瞎逼逼》是因为有人在知乎上黑Node.js。那篇文章的反响还是相当不错的,甚至连著名的hax贺老都很认同,下班时读那篇文章,竟然坐车的还坐过站了。大家可以很...

    Edison 评论0 收藏0
  • 【全文】狼叔:如何正确学习Node.js

    摘要:感谢大神的免费的计算机编程类中文书籍收录并推荐地址,以后在仓库里更新地址,声音版全文狼叔如何正确的学习简介现在,越来越多的科技公司和开发者开始使用开发各种应用。 说明 2017-12-14 我发了一篇文章《没用过Node.js,就别瞎逼逼》是因为有人在知乎上黑Node.js。那篇文章的反响还是相当不错的,甚至连著名的hax贺老都很认同,下班时读那篇文章,竟然坐车的还坐过站了。大家可以很...

    fengxiuping 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<