While reading a PluralSight Tutorial, it was claimed that a syntax error would prevent previous lines from being executed. 2();
and 2 = 3;
were both given as examples.
But upon testing this behavior in Chrome's Console, only 2 = 3;
prevented previous lines from executing.
Here's the output for 2();
(I'm using 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
And here is for 2 = 3;
console.log("foo 1");
2 = 3;
console.log("foo 2");
VM202:2 Uncaught ReferenceError: Invalid left-hand side in assignment
As you can see, the first line is executed for 2();
and foo 1
is printed out. But for 2 = 3;
, nothing is printed.
So why is one type of error preventing printing and execution of prior code, but the other doesn't, and is this browser-dependent?
This is due to the nature of the ReferenceError
. Per an answer of mine:
If you want to understand the syntax and semantics better, and why this throws a ReferenceError, you can delve into the ECMAScript® 2015 Language Specification. Per the 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.
Where IsValidSimpleAssignmentTarget
is:
Section 12.14.3 - Assignment Operators - Static Semantics: IsValidSimpleAssignmentTarget
AssignmentExpression : YieldExpression ArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression
1. Return false.
As you can see, an "early error" is raised if the assignment complies with the definition of AssignmentExpression : LeftHandSideExpression = AssignmentExpression
but LeftHandSideExpression
is invalid. Since 2
is not an ObjectLiteral
, ArrayLiteral
, and IsValidSimpleAssignmentTarget
returns false, the assignment fails and the ReferenceError
is thrown.
Now, to define the term "early error". Per the specification:
[...] 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.
That means none of the code is executed when an early error is raised. Because in your assignment, an early ReferenceError
is raised, none of the code is executed, and thus, the console is never logged to.
In the second example, a function call is performed. Step 5 of evaluation throws a TypeError
because the result of IsCallable(func)
is false (as func
is a Number
), and the TypeError
is thrown. Note that the TypeError
is not an early error. Thus, execution of code does happen, and the console is logged to. When the line 2();
is encountered, it is evaluated and the TypeError
is thrown.
This is not browser-dependent because all browsers and JavaScript engines must follow the specification. It should be noted that this was taken from the ECMAScript® 2015 (AKA ES6) Specification, which has not been fully implemented on all engines. I recommend taking a look in the ECMAScript® 2011 (ES5) Specification, in which all modern engines implement fully, though definitions of the above have not changed between both version.
It should be noted that these are not syntax errors. 2();
is a TypeError
because the Number
type is not callable. 2 = 3
is a ReferenceError
because 2
is an invalid left hand side to be assigned to. Assigning a function to a name that is a numeral is, however, a syntax error. It violates the syntax of a function declaration to do function 2() {}
, as the declaration expects an identifier as a name.
A numeral is a constant, you cannot assign a constant to anything because it is constant. 2 = 3
makes no sense in the real world, and is thus prevented in the specification. Similarly, you cannot do var 2 = function() {}
.