javascript异常
所谓异常就是程序的非正常运行,通俗的说就是程序发生了错误。至于这些错误,有的是认为疏忽造成的异常(Exception),有的是程序本身的错误(Error)。
比如有的时候我们希望两个数相加,因为人为疏忽,代码里写成了乘号,那么这种错误大部分情况下是得不到你想要的结果的,但是幸运又不幸的是,这个程序没有语法错误,依然可以返回结果,但是无法报错。
另一种情况就是你的程序无法被JavaScript引擎执行,这种异常引擎会抛出一个异常,这个时候如果你没有捕获异常,那么程序就会被中断,无法执行下去。
code1:
alert('js运行了!')
let a = b + 1
alert('程序结束')
这个时候我们的浏览器客户端作为JavaScript引擎就会捕获一条异常报告,俗称报错了。
因为此时代码中的 b 是尚未定义的,抛出了ReferenceError这个异常,下面是JavaScript中经常遇到的异常类型,大概分类有如下几种:
- EvalError: raised when an error occurs executing code in eval()
- RangeError: raised when a numeric variable or parameter is outside of its valid range
- ReferenceError: raised when de-referencing an invalid reference
- SyntaxError: raised when a syntax error occurs while parsing code in eval()
- TypeError: raised when a variable or parameter is not a valid type
- URIError: raised when encodeURI() or decodeURI() are passed invalid parameters
上面的六种异常对象都继承自Error对象。他们都支持以下两种构造方法: new Error();
new Error(“异常信息”);
try/catch/finlly语句
上面介绍了几种程序抛出的异常,那么现在就需要对异常进行处理,其中try从句中定义了需要处理和判断的代码块,catch从句中放置当程序发生异常后进行处理的代码,catch从句后跟随finally块,finally中放置清理代码,不管try块中是否产生异常。finally块中的逻辑代码都会执行,其中catch和finally都是可选的,但是必须选择两种中之一和try从句组成完整的语句。
try、catch、finally语句块都需要使用花括号括起来,即使语句中只有一条语句也不能省略,记住,这里的花括号是必须的
下面的代码说明了try/catch/finlly语句的用法和作用
try {
// 这里是你可能会出现异常的代码
// 可以通过throw直接抛出异常
// 或者通过调用一个方法间接抛出
} catch(e) {
// 当try语句块抛出了异常,这里的代码就会执行
// 可以通过局部变量e来获取该异常Error对象的信息
// 可以通过throw重新抛出异常
} finally {
// 无论是否抛出异常,都会执行这里的代码
// 终止语句块的方法有:
// 1. 正常执行最后一条语句终止
// 2. 通过break、continue、或return终止
// 3. 抛出异常,被try捕获
// 4. 抛出异常,异常未被捕获,继续向上传播
}
我们看到,catch后面接了个标识符e,这个标识符和函数参数很想,当捕获一个异常时,把和这个异常相关的值(比如Error对象)赋值给这个参数,和普通的变量不同,这条catch句中的标识符具有块级作用域,它只在catch语块内有定义。这个Error对象有几个主要属性,如下:
- description: 错误描述 (仅IE可用).
- fileName: 出错的文件名 (仅Mozilla可用).
- lineNumber: 出错的行数 (仅Mozilla可用).
- message: 错误信息 (在IE下同description)
- name: 错误类型.
- number: 错误代码 (仅IE可用).
- stack: 像Java中的Stack Trace一样的错误堆栈信息 (仅Mozilla可用).
下面就使用一个try/catch语句把pic1中的代码包裹起来
try{
//这里放置可能会出错的代码
let a = b + 1
} catch(e)
{
//代码出错后执行这里。
console.debug(' name: ' + e.name +
' message: ' + e.message +
' lineNumber: ' + e.lineNumber +
' fileName: ' + e.fileName +
' stack: ' + e.stack);
} finally {
console.log('执行了finally')
}
将上面的代码复制到chrome控制台,会看到下面的信息,说明异常已经被捕获,并且,最终执行了finally
通常状况下,解释器执行到try语句块的尾部,然后开始执行finally中的代码,以便进行必要的清理工作。当由于return、continue、break语句使得解释器跳出try语句块时,解释器在执行新的目标代码之前先执行finally中的代码。
如果在try中产生了异常,而且存在一条与之相关的catch从句来处理这个异常,解释器首先执行catch中的逻辑,然后执行finally中的逻辑,如果不存在处理异常的局部catch从句,解释器会首先执行finally中的逻辑,然后向上传播异常,直到找到能处理这个异常的catch从句。
如果finally快使用了return、continue、break或者throw语句时程序发生跳转,或者通过调用了抛出异常的方法改变了程序执行流程,不管这个跳转使程序挂起还是继续执行,解释器都会将其忽略。例如finally从句抛出一个异常,这个异常将替代正在抛出的异常。如果finally从句运行倒了return语句,尽管已经抛出了异常且这个异常还没有处理,这个方法依然会正常返回。
throw语句
在JavaScript运行的时候,若使用throw语句时就会电视的抛出异常。
throw语句的语法如下:
throw expression
expression的值是任意类型的。可以抛出代表错误码的数字亦或是让人明白意思的字符串。JavaScript解释器抛出异常的时候通常采用Error类型和其子类型。
function getMoney(money) {
// 若传入的参数非法,直接抛出异常
if (money < 0)
throw new Error('金额不能为负数')
return money
}
在chrome控制台里试试,这个时候如果传入的参数小于0就会直接抛出一个自定义字符串的异常了,见下图:
最后
当程序抛出异常时,JavaScript解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序,如果抛出异常的代码块中没有try/catch语句,解释器会检查更高层次的闭合代码块,看它是否有关联异常处理程序。以此类推,直到找到异常处理程序为止