{}[true]
есть [true]
и ![true]
должно быть false
.
Так зачем !{}[true]
оценивать true
?
javascript
user2430508
источник
источник
var o = {}; o[true] === undefined
,{}[true] === [true]
используете консоль, это потому, что она рассматривается{}
как пустой блок кода, а не как объект.{}
и({})
в консоли (или{}[true]
и({})[true]
). Кроме того, как никто не упомянул, объект [true] оценивается как объект ["true"].Ответы:
Я считаю, что это связано с тем, что plain
{}[true]
анализируется как пустой блок операторов (не литерал объекта), за которым следует массив, содержащийtrue
, который естьtrue
.С другой стороны, применение
!
оператора заставляет синтаксический анализатор интерпретировать{}
как литерал объекта, поэтому следующий{}[true]
элемент становится возвращаемым доступом к членуundefined
, и!{}[true]
он действительноtrue
(как!undefined
естьtrue
).источник
undefined
является ложным (то, на что мы часто полагаемся -if (obj.maybeExists) ...
), поэтому он имеет совершенный логический смысл, что!undefined
это правда.null
некоторых языках, с!undefined
равнымundefined
. Однако в Javascript это не так.not undefined
(!undefined
), должно быть определено. Если что-то определено, это обычно интерпретируется какtrue
.Потому
{}[true]
что не возвращаетtrue
, ноundefined
, иundefined
оценивается какfalse
:http://jsfiddle.net/67GEu/
источник
{}[true]
в консоли, вы получаете[true]
, потому что{}
интерпретируется как пустой блок кода, а не как объект. Все дело в контексте и неоднозначности{}
.{key:"value"}[1,2,3];
оценивает[1,2,3]
?key:
) и строковый литерал ("value"
), за которыми следует массив. Парсер по-прежнему не видит литерал объекта.alert()
илиconsole.log()
или назначите его переменной, вы измените контекст, поэтому он не ведет себя так же, как введенный сам по себе в консоли.Так как
оценивает
undefined
и!undefined
естьtrue
.Из @schlingel:
true
используется как ключ и{}
как хеш-карта. Не существует свойства с ключом,true
поэтому он возвращаетundefined
. Неundefined
будетtrue
, как и ожидалось.Консольный сеанс ( Node.js
[0.10.17]
):Однако в консоли Google Chrome :
Итак, никаких нестыковок. Вероятно, вы используете старую версию виртуальной машины JavaScript. Для тех, кому нужны дополнительные доказательства:
ОБНОВИТЬ
В Firefox он также оценивает
true
:источник
eval('{}[true]')
или напечатаете в консоли. Тогда, например, als{}"test"
естьtest
или даже{key:"value"}"test"
естьtest
.{}[true];
(с;
)[true]
для вас, потому что оно здесь?Причина путаницы кроется в неправильном понимании вашего первого утверждения:
{}[true]
является[true]
То, что вы видите при запуске, является результатом двусмысленности. Javascript имеет определенный набор правил относительно того, как обрабатывать подобные неоднозначности, и в этом случае он разбивает то, что вы видите как оператор signle, на два отдельных оператора.
Таким образом, Javascript рассматривает приведенный выше код как два отдельных оператора: во-первых, есть
{}
, а затем есть совершенно отдельный[true]
. Второе утверждение - это то, что дает вам результат[true]
. Первое утверждение{}
фактически полностью игнорируется.Вы можете доказать это, попробовав следующее:
т.е. заключить все в квадратные скобки, чтобы интерпретатор мог прочитать это как отдельную инструкцию.
Теперь вы увидите, что фактическая ценность вашего утверждения равна
undefined
. (это также поможет нам позже понять следующую часть)Теперь мы знаем, что начальная часть вашего вопроса - отвлекающий маневр, поэтому перейдем к последней части вопроса:
Здесь у нас есть то же утверждение, но с
!
добавленным перед ним.В этом случае правила Javascript говорят ему оценивать все как одно выражение.
Вернитесь к тому, что произошло, когда мы заключили предыдущее утверждение в скобки; мы получили
undefined
. На этот раз мы фактически делаем то же самое, но ставим!
перед ним символ. Таким образом, ваш код можно упростить как!undefined
:true
.Надеюсь, это немного это объясняет.
Это сложный зверь, но урок, который следует усвоить здесь, заключается в том, чтобы использовать скобки вокруг ваших операторов при их оценке в консоли, чтобы избежать подобных ложных результатов.
источник
{}[true]
это недействительным , просто двусмысленным . Его можно интерпретировать либо как «пустой блок кода, за которым следует литерал массива», либо как «литерал объекта без свойств, к свойству которого осуществляется доступ». Я не знаю, является ли первый технически случаем ASI (многие языки все равно не ставят точку с запятой), но суть проблемы заключается в контекстно-зависимой интерпретации.{}[true]
естьtrue
» они сказали «{}[true]
есть[true]
», что является одной из двух действительных интерпретаций двусмысленного утверждения.{}[true]
естьundefined
. Чтобы найти это, напишите следующее:или просто:
Мы знаем , что
!undefined
естьtrue
.Из ответа @Benjamin Gruenbaum :
Более подробную информацию можно найти в этом вопросе .
источник
Ответы здесь хорошие, вот разбивка псевдокода:
{}['whatever']
= пустой блок, NewArray ('что угодно') = NewArray ('что угодно'){}[true]
= пустой блок, NewArray (true) = NewArray (true)!{}['whatever']
= LogicalNOT (convertToBool (NewObject.whatever)) = LogicalNOT (convertToBool (undefined)) = LogicalNOT (false) = true({}['whatever'])
= Группировка (NewObject.whatever) = Группировка (undefined) = undefinedисточник
Это происходит потому, что
{}
в вашем понимании это не буквальное представлениеObject
, а пустая область видимости (или пустой блок кода):Он просто оценивает код внутри области видимости, а затем показывает ваш массив.
И от твоего
Просто преобразует эту область в int и возвращает тот же массив true. В этом коде нет логических проверок.
И если вы попытаетесь проверить результат,
{}[true]
вы получитеfalse
:Поскольку больше нет размаха.
Итак,
!
в своем вопросе сделайте то же самое:источник
var x = {}; x[true]
.!
это будет истолковано как пустой объект, а не сферы, и это несоответствие.{}
это объект без свойств.[]
непосредственно следует за объектом, это означает «Доступ к свойству с этим именем», а не «Создать массив».true
является логическим, но используется как имя свойства, поэтому преобразуется в строку ("true"
)true
(поскольку у него нет свойств), поэтому{}['true']
онundefined
!undefined
бросаетundefined
в булево (false
)false
вtrue
.источник
{}[true]
(без другого контекста){}
это не объект без свойств, это пустой блок кода.Вы не меняете ценность этого.
Проверьте это: Почему! Правда? 'false': 'true' возвращает 'true'?
источник
Давай поиграем еще немного!
Во-первых, повеселимся !:
Хорошо, давайте попробуем разобраться в этом безумном поведении, одно за другим:
1) Здесь
{}
анализируется как пустой блок кода. Без присваивания, отрицания, группировки (в круглых скобках) или любого синтаксиса, который указывает парсеру, что это{}
литерал объекта, по умолчанию предполагается, что это просто бесполезный пустой блок.Это доказательство такого поведения:
Приведенный выше код покажет предупреждение в обычном режиме и будет оцениваться так
[true]
же, как{}[true]
и.Блокировать заявления без точки с запятой
Оператор блочного типа не требует точки с запятой после него.
Например:
Отображаются оба предупреждения.
Итак, мы можем видеть, что оператор пустого блока без точки с запятой действителен и просто ничего не делает. Таким образом, когда вы входите
{}[true]
в консоль Developer Tools (или Firebug), оцененное значение будет значением последнего оператора выражения . В этом случае последний оператор выражения -[true]
.2) В контексте присваивания синтаксический анализатор убедится, что
{}
это литерал объекта. Когда вы делаете var a ={}[true]
, вы устраняете любую двусмысленность и отключаете синтаксический анализатор, который{}
не является оператором блока.Итак, здесь вы пытаетесь получить значение с помощью ключа
"true"
из пустого объекта. Очевидно, что с этим именем ключа не существует пары "ключ-значение". Таким образом, переменная не определена.Зарезервированные слова как ключи объекта
ECMAScript 5 позволяет объектным ключам быть зарезервированными словами. Итак, следующие ключи допустимы:
3) То же объяснение примера 1 . Но ... Если
{ b: 12345 }
часть трактуется как оператор блока, какой типb: 12345
оператора ??... (?????)
Это оператор метки , вы уже видели его раньше ... Он используется в циклах и in
switch
. Вот несколько интересных ссылок об операторах меток: 1 , (2) [ Лучший способ выйти из вложенных циклов в Javascript? , (3) [ Как разбить вложенные циклы в javascript? ,ПРИМЕЧАНИЕ: просто попробуйте оценить это:
Операторы меток не могут быть разделены оператором запятой , вам нужно будет разделить их точкой с запятой. Итак, это действительно так:
{a: 1; b: 2}
4) См. Пояснения к примерам 1 и 3 ...
5) Еще раз, у нас есть
{ b: 12345 }
обработка как блок кода, и вы пытаетесь получить доступ к свойству блока кода, используя точечную нотацию , и, очевидно, это не разрешено, и синтаксический анализатор выдает"Unexpected token :"
исключение.6) Код практически идентичен приведенному выше примеру, но окружая
{ b: 12345 }
заявление с оператором выражения группирования , анализатор будет знать , что является объектом. Таким образом, вы сможете получить доступ к"b"
собственности в обычном режиме.7) Помните пример 2 , здесь у нас есть присваивание, парсер знает, что
{ b: 12345 }
это объект.8) Идентично приведенному выше примеру, но вместо точечной записи мы используем скобки .
9) Я уже сказал, что этот
"identifier: value"
синтаксис внутри оператора блока является меткой. Но вы также должны знать, что имя метки не может быть зарезервированным ключевым словом (противоположным именам свойств объекта). Когда мы попытались определить метку с именем"true"
, мы получилиSyntaxError
.10) Опять же, мы имеем дело с объектом. Здесь нет проблем с использованием зарезервированных слов. знак равно
11) Наконец, у нас есть это:
!{}[true]
Давайте разделим вещи здесь:
а) Делая отрицание, мы информируя анализатор , что
{}
является объектом .б) Как показано в примере 2 ,
{}
объект не имеет вызываемого свойстваtrue
, поэтому это выражение будет оцениваться какundefined
.в) Конечный результат - отрицание
undefined
ценности. Javascript выполняет неявное преобразование типов , аundefined
значение является ложным .г) Итак, отрицание
false
...true
!источник