You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// 使用一个不存在的变量
unknownVariable
// Uncaught ReferenceError: unknownVariable is not defined
另一种触发场景是,将一个值分配给无法分配的对象,比如对函数的运行结果或者this赋值。
// 等号左侧不是变量
console.log() = 1
// Uncaught ReferenceError: Invalid left-hand side in assignment
// this 对象不能手动赋值
this = 1
// ReferenceError: Invalid left-hand side in assignment
var err1 = new Error('出错了!');
var err2 = new RangeError('出错了,变量超出有效范围!');
var err3 = new TypeError('出错了,变量类型无效!');
err1.message // "出错了!"
err2.message // "出错了,变量超出有效范围!"
err3.message // "出错了,变量类型无效!"
自定义错误
除了 JavaScript 原生提供的七种错误对象,还可以定义自己的错误对象。
function UserError(message) {
this.message = message || '默认信息';
this.name = 'UserError';
}
UserError.prototype = new Error();
UserError.prototype.constructor = UserError;
Error 实例对象
JavaScript 解析或运行时,一旦发生错误,引擎就会抛出一个错误对象。JavaScript 原生提供
Error
构造函数,所有抛出的错误都是这个构造函数的实例。上面代码中,我们调用
Error
构造函数,生成一个实例对象err
。Error
构造函数接受一个参数,表示错误提示,可以从实例的message
属性读到这个参数。抛出Error
实例对象以后,整个程序就中断在发生错误的地方,不再往下执行。JavaScript 语言标准只提到,
Error
实例对象必须有message
属性,表示出错时的提示信息,没有提到其他属性。大多数 JavaScript 引擎,对Error
实例还提供name
和stack
属性,分别表示错误的名称和错误的堆栈,但它们是非标准的,不是每种实现都有。使用
name
和message
这两个属性,可以对发生什么错误有一个大概的了解。stack
属性用来查看错误发生时的堆栈。上面代码中,错误堆栈的最内层是
throwit
函数,然后是catchit
函数,最后是函数的运行环境。原生错误类型
Error
实例对象是最一般的错误类型,在它的基础上,JavaScript 还定义了其他6种错误对象。也就是说,存在Error
的6个派生对象。SyntaxError 对象
SyntaxError
对象是解析代码时发生的语法错误。上面代码的错误,都是在语法解析阶段就可以发现,所以会抛出
SyntaxError
。第一个错误提示是“token 非法”,第二个错误提示是“字符串不符合要求”。ReferenceError 对象
ReferenceError
对象是引用一个不存在的变量时发生的错误。另一种触发场景是,将一个值分配给无法分配的对象,比如对函数的运行结果或者
this
赋值。上面代码对函数
console.log
的运行结果和this
赋值,结果都引发了ReferenceError
错误。RangeError 对象
RangeError
对象是一个值超出有效范围时发生的错误。主要有几种情况,一是数组长度为负数,二是Number
对象的方法参数超出范围,以及函数堆栈超过最大值。TypeError 对象
TypeError
对象是变量或参数不是预期类型时发生的错误。比如,对字符串、布尔值、数值等原始类型的值使用new
命令,就会抛出这种错误,因为new
命令的参数应该是一个构造函数。上面代码的第二种情况,调用对象不存在的方法,也会抛出
TypeError
错误,因为obj.unknownMethod
的值是undefined
,而不是一个函数。URIError 对象
URIError
对象是 URI 相关函数的参数不正确时抛出的错误,主要涉及encodeURI()
、decodeURI()
、encodeURIComponent()
、decodeURIComponent()
、escape()
和unescape()
这六个函数。EvalError 对象
eval
函数没有被正确执行时,会抛出EvalError
错误。该错误类型已经不再使用了,只是为了保证与以前代码兼容,才继续保留。总结
以上这6种派生错误,连同原始的
Error
对象,都是构造函数。开发者可以使用它们,手动生成错误对象的实例。这些构造函数都接受一个函数,代表错误提示信息(message)。自定义错误
除了 JavaScript 原生提供的七种错误对象,还可以定义自己的错误对象。
上面代码自定义一个错误对象
UserError
,让它继承Error
对象。然后,就可以生成这种自定义类型的错误了。throw 语句
throw
语句的作用是手动中断程序执行,抛出一个错误。上面代码中,如果变量
x
小于0
,就手动抛出一个错误,告诉用户x
的值不正确,整个程序就会在这里中断执行。可以看到,throw
抛出的错误就是它的参数,这里是一个Error
实例。throw
也可以抛出自定义错误。上面代码中,
throw
抛出的是一个UserError
实例。实际上,
throw
可以抛出任何类型的值。也就是说,它的参数可以是任何值。对于 JavaScript 引擎来说,遇到
throw
语句,程序就中止了。引擎会接收到throw
抛出的信息,可能是一个错误实例,也可能是其他类型的值。try…catch 结构
一旦发生错误,程序就中止执行了。JavaScript 提供了
try...catch
结构,允许对错误进行处理,选择是否往下执行。上面代码中,
try
代码块抛出错误(上例用的是throw
语句),JavaScript 引擎就立即把代码的执行,转到catch
代码块,或者说错误被catch
代码块捕获了。catch
接受一个参数,表示try
代码块抛出的值。如果你不确定某些代码是否会报错,就可以把它们放在
try...catch
代码块之中,便于进一步对错误进行处理。上面代码中,如果函数
f
执行报错,就会进行catch
代码块,接着对错误进行处理。catch
代码块捕获错误之后,程序不会中断,会按照正常流程继续执行下去。上面代码中,
try
代码块抛出的错误,被catch
代码块捕获后,程序会继续向下执行。catch
代码块之中,还可以再抛出错误,甚至使用嵌套的try...catch
结构。上面代码中,
catch
代码之中又抛出了一个错误。为了捕捉不同类型的错误,
catch
代码块之中可以加入判断语句。上面代码中,
catch
捕获错误之后,会判断错误类型(EvalError
还是RangeError
),进行不同的处理。finally 代码块
try...catch
结构允许在最后添加一个finally
代码块,表示不管是否出现错误,都必需在最后运行的语句。上面代码中,由于没有
catch
语句块,所以错误没有捕获。执行finally
代码块以后,程序就中断在错误抛出的地方。上面代码说明,
try
代码块没有发生错误,而且里面还包括return
语句,但是finally
代码块依然会执行。注意,只有在其执行完毕后,才会显示return
语句的值。下面的例子说明,
return
语句的执行是排在finally
代码之前,只是等finally
代码执行完毕后才返回。上面代码说明,
return
语句的count
的值,是在finally
代码块运行之前就获取了。下面是
finally
代码块用法的典型场景。上面代码首先打开一个文件,然后在
try
代码块中写入文件,如果没有发生错误,则运行finally
代码块关闭文件;一旦发生错误,则先使用catch
代码块处理错误,再使用finally
代码块关闭文件。下面的例子充分反映了
try...catch...finally
这三者之间的执行顺序。上面代码中,
catch
代码块结束执行之前,会先执行finally
代码块。catch
代码块之中,触发转入finally
代码块的标志,不仅有return
语句,还有throw
语句。上面代码中,进入
catch
代码块之后,一遇到throw
语句,就会去执行finally
代码块,其中有return false
语句,因此就直接返回了,不再会回去执行catch
代码块剩下的部分了。参考连接
The text was updated successfully, but these errors were encountered: