JavaScript异常处理总结

来源:互联网 发布:电暖气 知乎 编辑:程序博客网 时间:2024/06/02 02:12

使用抛出异常机制能让代码结构更加的简洁,减少很多的逻辑判断,并且能够得到出错时的详细错误信息,可说是好处多多,今天要说的就是在js中抛出(throw)异常。


一、语法

1. 可以抛出任何类型的异常,比如数字、字符串甚至布尔值

<script>    try {        throw 'error';        throw 123;        throw false;    }    catch (e) {        alert(e);    }</script>

2. 可以抛出自定义的对象

<script>    function CommonException(message, code) {        this.message = message;        this.code = code;    }    try {        var exception = new CommonException('您的代码出错啦', 1);        throw exception;        alert('这地方的代码将不会执行到');    } catch (e) {        alert(e.message);        alert(e.code)    }</script>

3. 内置的异常类Error

    new Error([message[, fileName[, lineNumber]]])  

Error具有下面一些主要属性:

  • 第一个参数代表错误提示信息(message)
  • 第二个是文件名
  • 第三个是行号。

简单示例:

<script>    try {        throw new Error('Whoops!');    } catch (e) {        alert(e.name + ': ' + e.message);    }</script>

4. 自定义异常类并继承Error基类

<script>    // Create a new object, that prototypically inherits from the Error constructor    function MyError(message) {        this.name = 'MyError';        this.message = message || 'Default Message';        this.stack = (new Error()).stack;    }    /*prototype是什么含义?*/    /*javascript中的每个对象都有prototype属性,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。*/    /*A.prototype = new B();*/    /*理解prototype不应把它和继承混淆。A的prototype为B的一个实例,可以理解A将B中的方法和属性全部克隆了一遍。A能使用B的方法和属性。    这里强调的是克隆而不是继承。可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。*/    MyError.prototype = Object.create(Error.prototype);    MyError.prototype.constructor = MyError;    try {        throw new MyError();    } catch (e) {        alert(e.name);     // 'MyError'        alert(e.message);  // 'Default Message'    }    try {        throw new MyError('custom message');    } catch (e) {        alert(e.name);     // 'MyError'        alert(e.message);  // 'custom message'    }</script>

5. 捕获处理特定的错误类

<script>    try {        throw RangeError("测试");    } catch (e) {        if (e instanceof EvalError) {            alert(e.name + ': ' + e.message);        } else if (e instanceof RangeError) {            alert(e.name + ': ' + e.message);        } else if (e instanceof MyError) {            alert(e.name + ': ' + e.message);        } else {            // etc...        }    }</script>

二、常见异常类型

1. SyntaxError - 解析错误

SyntaxError是解析代码时发生的语法错误

// 变量名错误var 1a;// 缺少括号console.log 'hello');

2. ReferenceError - 引用错误

ReferenceError是引用一个不存在的变量时发生的错误。将一个值分配给无法分配的对象,比如对函数的运行结果或者this赋值。

a// Uncaught ReferenceError: a is not definedthis=1;// Uncaught ReferenceError: Invalid left-hand side in assignmentnew abc// Uncaught ReferenceError: abc is not defined(…)

3. RangeError - 范围错误

RangeError是当一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number对象的方法参数超出范围,以及函数堆栈超过最大值。

new Array(-1)// Uncaught RangeError: Invalid array length(…)(1234).toExponential(21)//toExponential() 方法可把对象的值转换成指数计数法。参数为小数位0~20// Uncaught RangeError: toExponential() argument must be between 0 and 20(…)

4. TypeError - 类型错误

TypeError是变量或参数不是预期类型时发生的错误。比如,使用new字符串、布尔值、数值等原始类型和调用对象不存在的方法就会抛出这种错误,因为new命令的参数应该是一个构造函数。

new 1// Uncaught TypeError: 1 is not a constructor(…)var obj = {}; obj.a()// Uncaught TypeError: obj.a is not a function(…)

5. URIError - 统一资源标识符函数错误

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

decodeURI('%1')// Uncaught URIError: URI malformed(…)

6. EvalError - eval()函数执行错误

eval()函数没有被正确执行时,会抛出EvalError错误。该错误类型已经在ES5中不使用了,只是为了保证与以前代码兼容,才继续保留。

小结

以上这6种派生错误,连同原始的Error对象,都是JavaScript自带的构造函数。
开发者可以使用它们,人为生成错误对象的实例。
例一:

new Error("出错了!");

例二:

new RangeError("出错了,变量超出有效范围!");

例三:

try {    null.f();} catch (e) {    throw new SyntaxError("解析出错了!");}

三、使用案例

场景

有这样一个场景,我们在一个业务系统中,经常需要做表单元素的校验,比如:

var username = $("#username").val();var password = $("#password").val();if (username.length < 6) {    alert(“用户名长度不能小于6”);    return;}if (password.lengt < 6) {    alert(“密码长度不能小于6”);    return;}// ... ...

系统中到处都有类似这样的长度校验代码,我们会想能不能定义一个公共的方法进行校验,所以我们写了如下的方法:

function checkLength (str, len, msg) {    if (str.lengt < len) {        alert(msg);        return;    }}var username = $("#username").val();var password = $("#password").val();checkLength(username, 6, “用户名长度不能小于6”);checkLength(username, 6, “密码长度不能小于6”);// ... ...

写完上面的代码我们会发现并不能达到我们的目的,因为校验失败的话程序并不会终止。

解决方案

我们可以在校验方法里抛出一个异常强制终止程序。

function checkLength (str, len, msg) {    if (str.lengt < len) {        alert(msg);        throw Error(msg);    }}

这样就达到了我们想要的效果。


四、总结

JavaScript 拥有基本的异常处理方法,但是一般前端工程师都不会处理异常。
其实情有可原,对于普通网站来说,异常是非常可控的,基本可以刷新页面就解决问题,运行环境+代码运行也很少带来异常。
但是对于业务富集的webApp/大型组件来说,没有异常处理会是异常灾难。
无论在用户使用场景或者在开发/调试 作为出发点,异常处理都是非常必要的异常处理非常重要,它可以提高程序健壮性,对于软件开发来说,健壮性是非常重要的一项指标。

原创粉丝点击