【javaScript基础】异常处理

理解异常在javaScript面向对象编程是非常重要的,异常是一种非常强大的处理错误的方式。

错误处理

首先我们来看一个有问题的代码:

nonexistant();

在以上这个例子中,访问一个不存在的变量,在这种情况下,程序会怎么处理?很早以前的处理方式就是程序直接崩溃死掉,所以我们不能容忍这种处理方式,需要有办法来处理。

最简单的处理方式是先检查,像这样:

	if (window.func) {
  		func();
	}

上面这种处理方式,仍然可能还会出现错误。因为window.func可能不是一个函数,因此我们仍需要这样检查:

if (typeof(func) == 'function') {
    func();
}

在上面的例子中,typeof确保变量存在并确保是个函数。

我们满怀希望地做了很多需要的检查来确保执行func是安全的。但是如果func的函数体内有错误呢?我们更想做的是处理错误,而不是让程序死掉。

我们可以用trycatch结构来处理。

Try catch 结构

用try…catch来代替我们常用的if语句结构来处理错误,我们用如下代码来改写上面的例子:

	try {
	  func()
	} catch(e) {
	  alert(e)
	}

如果在try块中出现错误,这个时候catch块会起作用,参数e被赋值为一个特别的异常对象,该对象包括异常发生时的一些信息。

变量e是Error对象的一个实例(或者从TypeError,ReferenceError等继承)。

这个错误的属性在不同浏览器有点不一样,详情参考Error in MDN 和 Error
inMSDN

但是基本属性是相同的:

name:错误类型,对于浏览器产生的error会匹配error构造函数如TypeError, ReferenceError 等。

message: 告诉我们更详细的error信息。

在以下例子中,我们在try块中增加其他声明,name和message会被打印出来。

	try {
	  var a = 5
	  var res = func(a)
	  if (res > 0) doA()
	  else doB()

	} catch(e) {
	  alert("name:" + e.name + "\nmessage:" + e.message)
	}

很多异常都可以被try..catch捕获,你仅需通过try来检测可能的错误就行了。

获取栈的信息

Firefox,Chrome, Opera浏览器提供了stack属性,通过stack属性我们可以看到所有导致异常的嵌套的调用信息,例子如下:

	function f(a) {
	  g(a+1)
	}

	function g(a) {
	  notexists;
	}
	try { f(1) } catch(e) { alert(e.stack)

不幸的是在IE中没有这个属性,甚至在IE9中也没有。

Try…catch…finally完整形式

完整的组成形式是由3部分组成:

	try {
	   .. try statemenets ..
	} catch(exception) {
	   .. catch statements ..
	} finally {
	   .. finally statements ..

执行过程如下:

1. Try中的声明会被执行,如果没有错误发生,catch部分会被忽视。

2. 如果错误发生,exception变量会被赋值为错误对象,并且catch中的声明也会被执行。

3. 在以上两种情况下,在try或者catch中不管有没有执行,finally代码都会被执行。

try…catch…finally…return

在以下例子中,如果try中有return语句并且有finally块时,finally中的执行完后,执行return语句。

    function inc(a) {

	  try {
	    return a+1
	  } catch(e) {
	    // ..
	  } finally {
	    alert('done')
	  }
	}

	alert( inc(1) )
//执行结果:‘done’, 2

Throw声明

所有的错误可以被分成两种:

1. 程序设计错误:一般是由开发人员造成的,如输入错误。

2. 异常流错误:这个错误是程序执行过程中的正常部分。一个常见的错误是表单验证。如果用户输入了一些错误,正常的做法是处理这个错误并且叫用户重复输入。

用try…catch来处理异常错误,需要通过throw手动抛出错误。

语法是:throw e,e可以是任何东西。不管你抛出什么,都可以被catch…捕获,但是如果在try块外面抛出程序可能会崩溃。

下面的例子展示了throw是如何工作的。

	try {
	  throw 5
	} catch(e) {
	  alert("Caught: "+e)
	}

表单验证例子

例如,我们对年龄进行验证,检查是否合法。

function validateAge(age) { // age is a text to check
    if (age === '') return; // no age is valid
    age = +age
    if (isNaN(age)) {
        throw { name: 'BadAge', message: 'Invalid age' }
    }
    if (age < 5 || age > 150) {
        throw { name: 'BadAge', message: 'Age out of range' }
    }
}

try {
    var age = prompt("Enter your age please?")
    validateAge(age)
    alert("The age is accepted!")
} catch(e) {
    alert("Error: "+e.message)
}

经常来说,抛出的异常对象最好是从Error对象继承,提供一种更好的方式来管理error在上面的例子中应该这样实现:throw new BadAgeError("Invalid age")。

验证变化

现在如果需要添加一个验证条件,验证用户所提供的值是必须提供的,并且是有效的年龄。比如我们实现了validateAge和validateRequired。

错误的检测方法

var value = input.value

    // VALIDATE

    var error = validateRequired(value)

    if (!error) {
        error = validateAge(value)
    }

    if (!error) {
        /* another validator... */
    }
    // FINISHED VALIDATING
    if (error) {
        /* process error */
    } else {
        /* success */
}

Try…catch方法

这种方式就是当检测到错误时手动抛出。

    var value = input.value
	try {
	  validateRequired(value)
	  validateAge(value)
	  // other validators in a row

	  /* success */
	} catch(e) {
	  /* process error */
	}

我们不需要一个一个地来检测,只需要把可能出现错误的验证放到try块中就行了,如果一有错误,在catch中就会捕获到,没有错误自然很顺利地执行,不会进入到catch块中。

比较

用try..catch处理错误有一些优点和缺点:

1. Try…catch方法处理错误更干净、简单可依赖,能够捕获所有错误。

2. 有可能存在一些不能检测的异常,try…catch是唯一能解决的方法。例如检测浏览器的一些特性。

3. Try…catch结构会占据几行代码的位置,看起来代码不太优雅。

异常分析和重新抛出

有时代码会产生不同的错误,这种情况下,经常用if来选择正确的处理方式。以下是伪代码。

try {
	  // 1. do smth
	} catch(e) {
	  if (e instanceof ValidationError) {
	    // 2.1 process e
	  } else if (e instanceof PermissionError) {
	    // 2.2 process e
	  } else {
	    // 3. we don't know how to deal with e
	    throw e
	  }
	}

1. 在try块中的代码比较复杂,也许会抛出异常,有些异常我们知道怎么处理,比如ValidationError,但是其他一些异常不知道。

2. 在catch块中,我们分析异常并且处理它。

3. 否则,异常重新抛出,假定在外面还有一层try…catch块知道怎么处理该异常。

异常要么被重新抛出,要么被处理,千万不要不管它,除非你完全知道你在做什么。

	try {
	  func()
	} catch(e) {
	  if (e instanceof KnownError) {
	    // ...
	  }
	}

在上面代码片段中,除了KnownError异常外,其他异常都被忽视了。

坦白地说,在java的世界里有这种不处理异常的情况存在,但是留下不处理的异常总有隐患。

想象下,如果在func中代码有输入错误,这将会很难调试,因为TypeError 和ReferenceError 异常被忽视了。

总结

1. Try…catch…finally结构允许你在try块中加入几种声明,可以在各自的catch块中进行异常处理。

2.  允许处理所有错误,包括JS自己产生的和手动抛出的。

3.  严格来说javaScript允许throw任何值,但是推荐所有的错误继承Error对象,形成继承层级。在这种情况下,instanceof 工作得很好。例如你可以捕获所有e instanceof ValidationError的异常,ValidationError包括AgeValidationError, RequiredValidationError 等。

【javaScript基础】异常处理,布布扣,bubuko.com

时间: 2024-10-12 20:18:14

【javaScript基础】异常处理的相关文章

JavaScript基础细讲

JavaScript基础细讲 JavaScript语言的前身叫作Livescript.自从Sun公司推出著名的Java语言之后,Netscape公司引进了Sun公司有关Java的程序概念,将自己原有的Livescript 重新进行设计,并改名为JavaScript. JavaScript是一种基于对象和事件驱动并具有安全性能的脚本语言,有了JavaScript,可使网页变得生动.使用它的目的是与HTML超文本标识语言.Java 脚本语言一起实现在一个网页中链接多个对象,与网络客户交互作用,从而可

javascript基础学习(四)

javascript之流程控制语句 学习要点: 表达式语句含义 选择语句:if.if...else.switch 循环语句:while.do...while.for.for...in 跳转语句:break.continue 异常处理语句:throw.try...catch...finally 一.表达式语句 表达式语句通常是赋值语句.函数或方法调用语句等. 二.选择语句 if(条件表达式)语句;  if(条件表达式){语句;}else{语句;}   还有就是if...lese的嵌套 switch

史上最全、JavaScript基础篇

索宁 Hot summer nights mid July, when you and  I were forever wild. 首页 新随笔 联系 管理 随笔 - 12  文章 - 5  评论 - 19 史上最全.JavaScript基础篇 本章内容: 简介 定义 注释 引入文件 变量 运算符 算术运算符 比较运算符 逻辑运算符 数据类型 数字 字符串 布尔类型 数组 Math 语句 条件语句(if.switch) 循环语句(for.for in.while.do-while) label语

学习笔记 第十五章 JavaScript基础

第15章   JavaScript基础 [学习重点] 了解JavaScript基础知识 熟悉常量和变量 能够使用表达式和运算符 正确使用语句 能够掌握数据类型和转换的基本方法 正确使用函数.对象.数组等核心知识和技法 能够编写简单的脚本,解决网页中常见特效和互动效果 15.1  JavaScript入门 JavaScript是一种轻量级.解释型的Web开发语言.现代浏览器都已嵌入了JavaScript引擎./sc 15.1.1 在网页中插入JavaScript代码 使用<script>标签,可

JavaScript 基础学习1-day14

JavaScript 基础学习1 知识预览JavaScript概述二 JavaScript的基础三 JavaScript的对象BOM对象DOM对象实例练习js扩展 JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言) Netscape(网景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigator

web前端【第五篇】JavaScript基础

一.JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中).后将其改名ScriptEase.(客户端执行的语言) Netscape(网景)接收Nombas的理念,(Brendan Eich)在其Netscape Navigator 2.0产品中开发出一套livescript的脚本语言.Sun和Netscape共同完成.后改名叫Javascript 微软随后模仿在其IE3.0的产品中搭载了一个JavaScript的

javascript入门书籍推荐《javascript基础教程》

前段时间看javascript高级教程的时候,发现很多基础的javascript概念,自己不懂. 网上搜了一下,看到大家对<javascript基础教程(第8版)>评价不错,买了一本. 作者: (美)Tom Negrino Dori Smith 译者: 陈剑瓯 柳靖 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 翻开看了后,受益匪浅,决定将这本书推荐给javascript的入门童鞋. 这本书的读者,要有一定的HTML基础,因为javascript基本都是对Dom的操作,所以,有一定的HT

js基础--javascript基础概念之语法

掌握一门语言 必须先掌握它的语法! javascript 的语法和C.Java.Perl 的语法有些相似.但是比它们更加宽松. javascript 中的一切都是严格区分大小写的.例如变量: demo 和 Demo 两个变量是完全不同的. javascript 标示符,所谓标示符 是指 变量.函数.属性 的名字或函数的参数.标示符的格式是按照以下规则组合的一个或多个字符. 1.第一个字符必须是字母,下划线,或 $ 符号. 2.其他字符可以是字母.下划线.$ . 或数字. 注意 不能把关键字 保留

Javascript.01 -- Javascript基础

Javascript基础 1 聊聊Javascript 1.1 Javascript的历史来源 94年网景公司   研发出世界上第一款浏览器. 95年 sun公司   java语言诞生 网景公司和sun合作. Java+script   ===> javascript 1.2 W3c规范 ?结构标准        html ?表现标准   css ?行为标准      js 1.3 JavaScript和ECMAScript的关系 ECMAScript是一种由Ecma国际前身为欧洲计算机制造商协