为什么当这个TypeError没有时,这个ReferenceError会阻止所有执行?

时间:2017-02-24 16:39:00

标签: javascript syntax-error typeerror referenceerror

在阅读PluralSight Tutorial时,声称语法错误会阻止执行前一行。 2();2 = 3;都是作为示例提供的。

但是在Chrome的控制台中测试此行为后,只有2 = 3;阻止了以前的行执行。

以下是2();的输出(我正在使用 Shift + Enter ):

console.log("foo 1");
2();
console.log("foo 2");
VM224:1 foo 1
VM224:2 Uncaught TypeError: 2 is not a function
    at <anonymous>:2:2

这是2 = 3;

console.log("foo 1");
2 = 3;
console.log("foo 2");
VM202:2 Uncaught ReferenceError: Invalid left-hand side in assignment

如您所见,第一行是2();执行的,foo 1已打印出来。但是对于2 = 3;,没有任何内容被打印出来。

那么为什么一种类型的错误阻止了先前代码的打印和执行,而另一种则没有,并且这是依赖于浏览器的吗?

1 个答案:

答案 0 :(得分:4)

这是由于ReferenceError的性质。每an answer of mine

如果您想更好地理解语法和语义,以及为什么会引发ReferenceError,您可以深入研究ECMAScript® 2015 Language Specification。根据规范:

  

Section 12.14.1 - Assignment Operators - 静态语义:早期错误

     

AssignmentExpression : LeftHandSideExpression = AssignmentExpression

     如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 {

这是一个早期参考错误 ArrayLiteral 的{1}} IsValidSimpleAssignmentTarget 为false。

LeftHandSideExpression的位置:

  

Section 12.14.3 - Assignment Operators - 静态语义:IsValidSimpleAssignmentTarget

IsValidSimpleAssignmentTarget
     

1。返回false。

如您所见,如果作业符合 AssignmentExpression : YieldExpression ArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression 的定义但 AssignmentExpression : LeftHandSideExpression = AssignmentExpression 无效,则会引发“早期错误” 。由于LeftHandSideExpression不是 2 ObjectLiteral ,而ArrayLiteral返回false,因此分配失败并且{ {1}}被抛出。

现在,定义术语“早期错误”。根据规范:

  

<强> Section 16 - Errors

     

[...] 早期错误是在评估包含错误的Program中的任何构造之前可以检测和报告的错误。

这意味着当引发早期错误时,不会执行任何代码。因为在你的作业中,引发了早期的IsValidSimpleAssignmentTarget,所以没有执行任何代码,因此,控制台永远不会被记录。

在第二个示例中,执行function call。评估的第5步会引发ReferenceError,因为IsCallable(func)的结果为假(ReferenceErrorTypeError),并且func被抛出。请注意,Number 不是早期错误。因此,代码的执行确实发生,并且控制台被记录到。遇到行TypeError时,会对其进行评估并抛出TypeError

不依赖浏览器,因为所有浏览器和JavaScript引擎都必须遵循规范。应该注意的是,这取自ECMAScript® 2015 (AKA ES6)规范,该规范尚未在所有引擎上完全实现。我建议看看ECMAScript® 2011(ES5)规范,其中所有现代引擎都完全实现,但上述两个版本之间的定义没有变化。

应该注意,这些不是语法错误。 2();TypeError,因为2();类型不可调用。 TypeErrorNumber,因为2 = 3是要分配的无效左侧。但是,将函数分配给数字名称是语法错误。它违反function declarationReferenceError的语法,因为声明需要identifier作为名称。

数字是常量,您不能为任何事物分配常量,因为它是常量。 2在现实世界中毫无意义,因此在规范中被禁止。同样,您无法执行function 2() {}