(4 || x = 5) ReferenceError вместо SyntaxError
Почему следующий код возвращает ReferenceError
вместо SyntaxError
?
4 || x = 5; // Uncaught ReferenceError: Invalid left-hand side in assignment
Вот как AssignmentExpression
определяется в соответствии с ECMAScript 5.1:
AssignmentExpression :
ConditionalExpression
LeftHandSideExpression = AssignmentExpression
LeftHandSideExpression AssignmentOperator AssignmentExpression
В этом случае 4 || x
это не LeftHandSideExpression, а LogicalORExpression
это не входит в LeftHandSideExpression
, Как работает парсер?
3 ответа
Это синтаксически неверно, и по спецификации вы должны получить SyntaxError, но ваш браузер странно относится к типу исключения.
Вы должны получить раннюю ReferenceError для таких случаев, как
1 = 2;
где грамматика говорит, что левая сторона в порядке, но левая сторона не является ни литералом массива, ни литералом объекта, а IsValidSimpleAssignmentTarget не является истинным для левой стороны. Вы должны получить SyntaxError, когда грамматика отклоняет ваш код (и в некоторых других случаях тоже). Похоже, ваш браузер использует слишком разрешающую версию LeftHandSideExpression и отфильтровывает грамматически неверные левые части в той же проверке, что и IsValidSimpleAssignmentTarget, и выдает ту же ошибку.
Интересная находка! Я считаю, что сканер читает слева направо. Сначала это оценка 4 || x
, Результат этого выражения всегда будет 4
, поскольку 4
"правда". Таким образом, он затем оценивает 4 = 5
, который выдает ошибку, так как вы не можете переопределить значение целого числа.
Дополнительную информацию о порядке приоритета можно найти здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
Мои знания JavaScript говорят мне, что "=" имеет меньший приоритет, чем логическое ИЛИ "||" вот почему вы получаете ReferenceError..
делая это:
4 || (x = 5)
вы вообще не получаете ошибку
отредактировано: внимательно читая ваш вопрос.. что вы действительно хотите знать, так это то, как работает синтаксический анализатор.. ну..JS - интерпретируемый язык и пытается быть быстрым, так
true || destroyWorld() // will never be called.. actually..the parser will never read it
когда я добавил скобки, я увеличил приоритет всего выражения.. оператор присваивания имеет один из самых низких
(проверьте ссылку в другом ответе)