为什么这个 ReferenceError 会阻止所有执行而这个 TypeError 不会?
Why does this ReferenceError prevent all execution when this TypeError does not?
在阅读 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;
,什么都不打印。
那么,为什么一种类型的错误会阻止先前代码的打印和执行,而另一种则不会,这是否取决于浏览器?
这是 ReferenceError
的性质造成的。每 :
如果您想更好地理解语法和语义,以及为什么会抛出 ReferenceError,您可以深入研究 ECMAScript® 2015 Language Specification。根据规范:
Section 12.14.1 - Assignment Operators - Static Semantics: Early Errors
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
It is an early Reference Error if LeftHandSideExpression
is neither an ObjectLiteral
nor an ArrayLiteral
and IsValidSimpleAssignmentTarget
of LeftHandSideExpression
is false.
其中 IsValidSimpleAssignmentTarget
是:
Section 12.14.3 - Assignment Operators - Static Semantics: IsValidSimpleAssignmentTarget
AssignmentExpression :
YieldExpression
ArrowFunction
LeftHandSideExpression = AssignmentExpression
LeftHandSideExpression AssignmentOperator AssignmentExpression
1. Return false.
如您所见,如果赋值符合 AssignmentExpression : LeftHandSideExpression = AssignmentExpression
但 [=13 的定义,则会引发 "early error" =] 无效。由于 2
不是 ObjectLiteral
、ArrayLiteral
和 IsValidSimpleAssignmentTarget
returns false,赋值失败并抛出 ReferenceError
。
现在,定义术语"early error"。根据规范:
[...] An early error is an error that can be detected and reported prior to the evaluation of any construct in the Program
containing the error.
这意味着 none 的代码在出现早期错误时执行。因为在您的作业中,引发了早期的 ReferenceError
,执行了 none 代码,因此永远不会登录到控制台。
在第二个示例中,function call is performed. Step 5 of evaluation throws a TypeError
because the result of IsCallable(func)
为假(因为 func
是 Number
),并且抛出 TypeError
。请注意 TypeError
是 而不是 早期错误。因此,确实会执行代码,并且会记录到控制台。当遇到行 2();
时,对其求值并抛出 TypeError
。
这 不 浏览器相关,因为所有浏览器和 JavaScript 引擎都必须遵循规范。应该注意的是,这取自 ECMAScript® 2015 (AKA ES6) 规范,该规范尚未在所有引擎上完全实现。我建议查看 ECMAScript® 2011 (ES5) 规范,其中所有现代引擎都完全实现,尽管上述定义在两个版本之间没有改变。
需要注意的是,这些不是语法错误。 2();
是 TypeError
因为 Number
类型不可调用。 2 = 3
是 ReferenceError
因为 2
是要分配给的无效左侧。但是,将函数分配给数字名称是语法错误。它违反了 function declaration to do function 2() {}
, as the declaration expects an identifier 作为名称的语法。
数字是常量,你不能将常量分配给任何东西,因为它是常量。 2 = 3
在现实世界中没有意义,因此在规范中被禁止。同样,你不能做 var 2 = function() {}
.
在阅读 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;
,什么都不打印。
那么,为什么一种类型的错误会阻止先前代码的打印和执行,而另一种则不会,这是否取决于浏览器?
这是 ReferenceError
的性质造成的。每
如果您想更好地理解语法和语义,以及为什么会抛出 ReferenceError,您可以深入研究 ECMAScript® 2015 Language Specification。根据规范:
Section 12.14.1 - Assignment Operators - Static Semantics: Early Errors
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
It is an early Reference Error if
LeftHandSideExpression
is neither anObjectLiteral
nor anArrayLiteral
andIsValidSimpleAssignmentTarget
ofLeftHandSideExpression
is false.
其中 IsValidSimpleAssignmentTarget
是:
Section 12.14.3 - Assignment Operators - Static Semantics: IsValidSimpleAssignmentTarget
AssignmentExpression : YieldExpression ArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression
1. Return false.
如您所见,如果赋值符合 AssignmentExpression : LeftHandSideExpression = AssignmentExpression
但 [=13 的定义,则会引发 "early error" =] 无效。由于 2
不是 ObjectLiteral
、ArrayLiteral
和 IsValidSimpleAssignmentTarget
returns false,赋值失败并抛出 ReferenceError
。
现在,定义术语"early error"。根据规范:
[...] An early error is an error that can be detected and reported prior to the evaluation of any construct in the
Program
containing the error.
这意味着 none 的代码在出现早期错误时执行。因为在您的作业中,引发了早期的 ReferenceError
,执行了 none 代码,因此永远不会登录到控制台。
在第二个示例中,function call is performed. Step 5 of evaluation throws a TypeError
because the result of IsCallable(func)
为假(因为 func
是 Number
),并且抛出 TypeError
。请注意 TypeError
是 而不是 早期错误。因此,确实会执行代码,并且会记录到控制台。当遇到行 2();
时,对其求值并抛出 TypeError
。
这 不 浏览器相关,因为所有浏览器和 JavaScript 引擎都必须遵循规范。应该注意的是,这取自 ECMAScript® 2015 (AKA ES6) 规范,该规范尚未在所有引擎上完全实现。我建议查看 ECMAScript® 2011 (ES5) 规范,其中所有现代引擎都完全实现,尽管上述定义在两个版本之间没有改变。
需要注意的是,这些不是语法错误。 2();
是 TypeError
因为 Number
类型不可调用。 2 = 3
是 ReferenceError
因为 2
是要分配给的无效左侧。但是,将函数分配给数字名称是语法错误。它违反了 function declaration to do function 2() {}
, as the declaration expects an identifier 作为名称的语法。
数字是常量,你不能将常量分配给任何东西,因为它是常量。 2 = 3
在现实世界中没有意义,因此在规范中被禁止。同样,你不能做 var 2 = function() {}
.