Странное поведение сравнения объектных литералов
Я искал, но не смог найти логику следования в JavaScript.
Когда я печатаю в консоли Chrome:
{} == null
это возвращается
Uncaught SyntaxError: Неожиданный токен ==
Но
{} == {}
а также
{} == function(){}
возвращает ложь
Зачем?
4 ответа
Я полагаю, вы понимаете, почему {} == null
бросает SyntaxError
, Короче говоря, это потому, что {
в начале, начиная с блока, оператор не является литералом объекта. Вы можете проверить ответ здесь
Как и почему {} == {}
это работает.
Если вы проверите код хрома, который оценивает выражения в консоли. Вы можете найти следующее ( код)
if (/^\s*\{/.test(text) && /\}\s*$/.test(text))
text = '(' + text + ')';
executionContext.evaluate(text, "console", !!useCommandLineAPI, false, false, true, printResult);
Этот код переносит {} == {}
код с круглыми скобками, делающий его допустимым выражением ({} == {})
сравнивая два пустых литерала объекта. Который оценивает false
потому что объекты сравниваются по ссылке.
Узел repl имеет такое же поведение src
if (/^\s*\{/.test(code) && /\}\s*$/.test(code)) {
// It's confusing for `{ a : 1 }` to be interpreted as a block
// statement rather than an object literal. So, we first try
// to wrap it in parentheses, so that it will be interpreted as
// an expression.
code = `(${code.trim()})\n`;
wrappedCmd = true;
}
Вы можете найти это в спецификации под Заявлением (статья 12)
12 - Заявление
Утверждение:
Блок. ВыраженияПрисваивания
EmptyStatement
ExpressionStatement
,
,
,
Первыми применимыми правилами являются либо блок, либо оператор выражения. Итак, нам нужно взглянуть на 12.4.
В 12.4 спецификации четко утверждают, что выражение выражения не может начинаться с {
,
хотя я еще не нашел, что делает пример 2 выражением, может быть, это зависит от реализации
12.4 Выражение выражения
Синтаксис ExpressionStatement: [lookahead ∉ {{, function}] Expression;
ПРИМЕЧАНИЕ ExpressionStatement не может начинаться с открывающей фигурной скобки, поскольку это может сделать его неоднозначным с блоком. Кроме того, ExpressionStatement не может начинаться с ключевого слова function, потому что это может сделать его неоднозначным с FunctionDeclaration.
Семантика Производство ExpressionStatement: [lookahead ∉ {{, function}] Expression; оценивается следующим образом:
Пусть exprRef будет результатом вычисления Expression. Возврат (обычный, GetValue(exprRef), пустой).
Я бы сказал, что это проблема разбора, а не логическая проблема как таковая.
В Chrome я получаю наблюдаемое поведение.
В IE я получаю синтаксические ошибки всякий раз, когда я ставлю {}
(или, кажется, любой объектный литерал) на LHS ==
,
В обоих браузерах выкладываю ()
вокруг выражения фиксированные вещи. Или сначала присвоить объект переменной
var x = {}
x == null
Я бы сказал, что это кажется мне ошибкой при разборе. Правда ли это в академическом смысле потребует копаться в спецификациях и грамматиках; практический ответ: есть достаточно простые обходные пути, поэтому лучше всего не делать этого.
Это потому, что JavaScript отстой. Причина, по которой он не работает, заключается в том, что JavaScript берет тип, который сравнивает первый объект.
Например
3+”1” = 4
Но
“3”+1 = 31
Первый пример выполняет операцию как число, потому что первый объект является числом. Второй пример рассматривает строку как первый объект и рассматривает операцию как конкатенацию строки.
Для вашего примера {} является объектом, но нуль не может быть преобразован в объект
Это работает по-другому, потому что {} может быть представлен как нулевой объект.