JavaScript (九) 异常处理与严格模式
Error 对象
当代码运行时发生错误,会立刻中止当前 JavaScript 的执行,同时会创建新的 Error
对象,并将其抛出( throw )
错误类型:
SyntaxError
语法错误,当 JavaScript 引擎在解析代码时,如果遇到不符合语法规范的 tokens 或 token顺序时,就会抛出 SyntaxError例:
1
2
3console.log([) //SyntaxError: Unexpected token ')'
var = 1; //SyntaxError: Unexpected token '='
{ //SyntaxError: Unexpected end of inputReferenceError
引用错误,当一个不存在的变量被引用时发生的错误例:
1
2
3
4
5//访问未声明的变量
console.log(author); //ReferenceError: b is not defined
//给函数调用表达式赋值
function fun(){}
fun() = 123; //ReferenceError: Invalid left-hand side in assignmentRangeError
范围错误,当一个值不在其所允许的范围中时则抛出该错误例:
1
2
3
4
5
6
7
8
9
10//数组长度为负数
[].length = -1; //RangeError: Invalid array length
//Number 对象的方法参数超出范围
const num = new Number(12.34);
console.log(num.toFixed(-1)); //RangeError: toFixed() digits argument must be between 0 and 20 at Number.toFixed
//调用栈超过最大值
function foo(){
foo()
}
foo(); //RangeError: Maximum call stack size exceededTypeError
类型错误,值的类型或参数不是预期类型时发生的错误例:
1
2
3
4
5//调用不存在的方法
const person = {};
person.run(); //TypeError: person.run is not a function
//new 操作符后面不是构造函数
const instance = new 2(); //TypeError: 2 is not a constructorURIError
URI错误,使用全局 URI 处理函数而产生的错误例:
1
2decodeURI("%"); //URIError: URI malformed
decodeURIComponent("%"); //URIError: URI malformed
自定义错误
例:
1 | function DiyError(message) { |
上面代码自定义一个错误对象DiyError
,让它继承Error
对象。然后,就可以生成这种自定义类型的错误了
1 | // 抛出一个 DiyError 类型错误 |
PS:throw
语句的作用是手动中断程序执行,抛出一个错误
try…catch 语句
一旦发生错误,程序就中止执行了。JavaScript 提供了try...catch
语句,允许对错误进行处理,选择是否往下执行
例1:
1 | try { |
在 try 块中的代码,发生错误时,会立即执行 catch 块中的代码,并将发生错误的错误对象作为 catch 块的参数传递( 可以省略 ),你可以在 catch 块中决定是否让程序继续执行。而 finally 块中的代码会在 catch 块执行结束后执行,用于做一些资源清理操作
例2:
1 | try { |
严格模式
在ES5中增加了一种运行模式,即严格模式(strict mode),该模式可以使JavaScript在更严格的条件下运行
严格模式的目的:
- 消除 Js 语法的一些不合理、不严谨之处,减少一些怪异行为
- 消除代码运行的一些不安全之处,保证代码运行的安全
- 提高编译器效率,提升执行速度
- 为未来新版本的 JavaScript 做好铺垫
开启严格模式
通过 "use strict"
这个特殊语句来开启严格模式
语法:
1 |
|
开启严格模式后的变化
1.禁止意外创建全局变量
在非严格模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法
例:
1 | function fn() { |
2.静默失败(不报错也没生效)转为抛出异常
例1:
1 | /* 在非严格模式下为只读属性赋值 */ |
1 | /* 在严格模式下为只读属性赋值 */ |
例2:
1 | /* 在非严格模式下为不可扩展对象的新属性赋值 */ |
1 | /* 在严格模式下为不可扩展对象的新属性赋值 */ |
例3:
1 | /* 在非严格模式下使用 delete 运算符未删除成功 */ |
1 | /* 在严格模式下使用 delete 运算符未删除成功 */ |
3.禁止函数中出现重复的参数名
例:
1 | /* 非严格模式 */ |
1 | /* 严格模式 */ |
4.禁止使用八进制数字(0开头)
例:
1 |
|
5.禁止将 eval 作为标识符
eval() 是全局对象中的方法,作用是将一个字符串作为 Js 代码执行,如:eval("var a = 666;console.log(a)")
,在严格模式中 eval 不能作为标识符
例:
1 | /* 非严格模式 */ |
1 | /* 严格模式 */ |
6.禁止将 arguments[i] 赋值给实参或实参赋值给 arguments[i]
在严格模式中 arguments 不能作为标识符
例:
1 | function f(a) { |
7.禁止使用 arguments.callee()
方法
例:
1 | ; |
8.严格模式中函数中的 this 默认值为 undefined
例:
1 | function fn(){ |
9.允许通过函数的call()、apply()、bind()方法将函数中 this 的值指定为 null 或 undefined(任何值)
1 | /* 未开启严格模式 */ |
10.标示符的限制
未来版本的 ECMAScript 很有可能会引入新语法,ECMAScript5 中的严格模式就提早设置了一些限制来减轻之后版本改变产生的影响
在严格模式中一部分字符变成了保留的关键字。这些字符包括implements
, interface
, let
, package
, private
, protected
, public
, static
和yield
。在严格模式下,你不能再用这些名字作为变量名或者形参名