Почему? {} [True] оценивает значение true в JavaScript?

{}[true] [true] и ![true] должен быть false.

Итак, почему !{}[true] оценивается на true?

Ответ 1

Я считаю, что, поскольку plain {}[true] анализируется как пустой операторный блок (а не литерал объекта), за которым следует массив, содержащий true, который является true.

С другой стороны, применение оператора ! делает синтаксический анализатор интерпретирует {} как литерал объекта, поэтому следующий {}[true] становится членом доступа, который возвращает undefined, а !{}[true] действительно true > (как !undefined есть true).

Ответ 2

Поскольку {}[true] не возвращает true, но undefined и undefined оценивается как false:

http://jsfiddle.net/67GEu/

'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true

Ответ 3

Поскольку

{}[true]

оценивается как undefined, а !undefined - true.

От @schlingel:

true используется как ключ и {} как хэш-карта. Не существует свойства с ключом true, поэтому он возвращает undefined. Не undefined true, как и ожидалось.

Консольный сеанс (Node.js [0.10.17]):

> {}[true]
undefined
> !{}[true]
true
> [true]
[ true ]
> ![true]
false
>

Однако в консоли Google Chrome:

> !{}[true]
true

Итак, никаких несоответствий. Вероятно, вы используете старую версию VMware JavaScript. Для тех, кто нуждается в дополнительных доказательствах:

Enter image description here

UPDATE

С Firefox он также оценивает true:

Enter image description here

Ответ 4

Причина путаницы сводится к непониманию вашего первого утверждения:

{}[true] [true]

То, что вы видите при запуске, является результатом двусмысленности. Javascript имеет определенный набор правил относительно того, как обрабатывать двусмысленности, подобные этому, и в этом случае он разбивает то, что вы видите как оператор signle, на два отдельных оператора.

Итак, Javascript видит вышеуказанный код как два отдельных оператора: во-первых, существует {}, а затем есть полностью отдельный [true]. Второе утверждение - это то, что дает вам результат [true]. Первое утверждение {} полностью игнорируется.

Вы можете доказать это, попробовав следующее:

({}[true])

т.е. обернуть все это в скобках, чтобы заставить интерпретатор читать его как единый оператор.

Теперь вы увидите, что фактическое значение вашего оператора undefined. (это также поможет нам позже понять следующую часть)

Теперь мы знаем, что начальная часть вашего вопроса - красная селедка, поэтому давайте перейдем к заключительной части вопроса:

Итак, почему? {} [true] оценивает true?

Здесь мы имеем то же утверждение, но с !, добавленным к нему.

В этом случае правила Javascript говорят, что он оценивает всю вещь как единый оператор.

Обратитесь к тому, что произошло, когда мы завернули предыдущий оператор в скобках; мы получили undefined. На этот раз мы делаем то же самое, но ставим перед ним !. Таким образом, ваш код можно упростить как !undefined, который true.

Надеюсь, это немного объяснит.

Это сложный зверь, но урок для изучения здесь - использовать скобки вокруг своих утверждений при оценке их в консоли, чтобы избежать ложных результатов, подобных этому.

Ответ 5

{}[true] undefined. Найти это:

a = {};
a[true] === undefined // true

или просто:

({})[true] === undefined // true

Мы знаем, что !undefined true.


Из @Benjamin Gruenbaum ответ:

Инструменты разработчика Chrome делают следующее:

  try {
      if (injectCommandLineAPI && inspectedWindow.console) {
          inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
          expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
      }
      var result = evalFunction.call(object, expression);
      if (objectGroup === "console")
          this._lastResult = result;
      return result;
  } 
  finally {
      if (injectCommandLineAPI && inspectedWindow.console)
          delete inspectedWindow.console._commandLineAPI;
  }

В основном, он выполняет call для объекта с выражением. Выражение:

with ((window && window.console && window.console._commandLineAPI) || {}) {
    {}+{};// <-- This is your code
}

Итак, как вы можете видеть, выражение вычисляется напрямую, без скобок.

Более подробную информацию можно найти в этом вопросе.

Ответ 6

Ответ здесь хорош, здесь разбивка на псевдокод:

  • {}['whatever']= пустой блок, NewArray ('whatever') = NewArray ('whatever')
  • {}[true]= пустой блок, NewArray (true) = NewArray (true)
  • !{}['whatever']= LogicalNOT (convertToBool (NewObject.whatever)) = ЛогическийNOT (convertToBool (undefined)) = ЛогическийNOT (false) = true
  • ({}['whatever'])= Группирование (NewObject.whatever) = Группирование (undefined) = undefined

Ответ 7

Это происходит потому, что {} в вашем значении не является литеральным представлением Object, а пустой областью (или пустым блоком кода):

{ var a = 1 }[true] // [true] (do the same thing)

Он просто оценивает код внутри области видимости и показывает ваш массив.

И из вашего

!{}[true]

Просто преобразует в int эту область и возвращает тот же самый массив true. В этом коде нет проверок bool.

И если вы попытаетесь проверить результат с {}[true], вы получите свой false:

{}[true] -> [true] -> ![true] -> false

Поскольку больше нет области видимости.

Итак ! в вашем вопросе сделайте то же самое, что:

!function() {
   //...
}

Ответ 8

  • {} - объект без свойств.
  • Так как [] сразу следует за объектом, это означает "Доступ к свойству этого имени", а не "Создать массив"
  • true является логическим, но используется как имя свойства, поэтому он передается в строку ("true")
  • Объект не имеет свойства, называемого true (поскольку он не имеет свойств), поэтому {}['true'] есть undefined
  • !undefined добавляет undefined в булевское (false)
  • Не оператор превращает false в true.

Ответ 10

Давайте играть немного больше!

Во-первых, пусть будет весело!:

//----------#01#-----------
{}[true]; //[true]

//----------#02#-----------
var a = {}[true]; 
      console.log(a); //undefined

//----------#03#-----------
{ b: 12345 }[true]; //[true]

//----------#04#-----------
{ b: 12345 }["b"]; //evaluates to ["b"] ?!?

//----------#05#-----------
{ b: 12345 }.b; // "Unexpected token ."

//----------#06#-----------
({ b: 12345 }).b; //12345

//----------#07#-----------
var c = { b: 12345 }.b; 
      console.log(c); //12345

//----------#08#-----------
var c = { b: 12345 }["b"];
      console.log(c); //12345

//----------#09#-----------
{ true: 54321 }[true]; // "SyntaxError: Unexpected token : "

//----------#10#-----------
var d = { true: 54321 }[true]; //No error here ¬¬
      console.log(d); //54321

//----------#11#-----------
!{}[true]; // true

Хорошо, попробуем разобраться в этом сумасшедшем поведении: один за другим:

1) Здесь {} анализируется как пустой блок кода. Без назначения, отрицания, группировки (с круглыми скобками) или любого синтаксиса, который указывает синтаксическому анализатору, что этот {} является литералом объекта, по умолчанию предполагается, что это просто бесполезный пустой блок.

Это доказательство этого поведения:

{ alert(123) }[true]

В приведенном выше коде будет отображаться предупреждение в обычном режиме и будет оцениваться как [true], таким же образом {}[true].

Блочные выражения без запятой

Оператор типа блока не нуждается в запятой после него.

Например:

for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")

Отображаются оба предупреждения.

Итак, мы видим, что пустой оператор блока без точки с запятой действителен и просто ничего не делает. Таким образом, когда вы вводите {}[true] в консоли разработчика (или Firebug), оцененное значение будет значением последнего выражения выражение. В этом случае последний оператор выражения [true].

2) В контексте назначения анализатор будет убедиться, что {} является литералом объекта. Когда вы выполняете var a = {}[true], вы удаляете любую двусмысленность и опрокидываете синтаксический анализатор, что {} не является выражением блока.
Итак, здесь вы пытаетесь получить значение с помощью ключа "true" из пустого объекта. Очевидно, что нет пары ключ-значение с этим именем ключа. Таким образом, переменная undefined.

Зарезервированные слова как ключи объектов

ECMAScript 5 позволяет клавишам объектов зарезервировать слова. Итак, следующие ключи являются законными:

var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}

3) То же объяснение примера 1. Но... Если часть { b: 12345 } рассматривается как оператор блока, то какой тип оператора b: 12345

... (?????)

Это выражение , вы уже видели его раньше... Он используется в циклах и в switch. Вот несколько интересных ссылок о операторах ярлыков: 1, (2) [Лучший способ выйти из вложенных циклов в Javascript?, (3) [Как разбить вложенные циклы в javascript?.

ПРИМЕЧАНИЕ: Просто попробуйте оценить это:

{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :

Операторы ярлыков не могут быть разделены оператором comma, вам нужно будет разделить их точкой с запятой. Так что это действительно: {a: 1; b: 2}

4) См. пояснения к примерам 1 и 3...

5) Еще раз мы имеем { b: 12345 }, который рассматривается как кодовый блок, и вы пытаетесь получить доступ к свойству блока кода с помощью dot notation, и, очевидно, это недопустимо, и синтаксический анализатор генерирует исключение "Unexpected token :".

6) Код почти идентичен приведенному выше примеру, но, окружая оператор { b: 12345 } с помощью группировки выражений оператора, парсер будет знать, что это объект. Таким образом, вы сможете нормально получить доступ к свойству "b".

7) Помните пример 2, здесь у нас есть назначение, синтаксический анализатор знает, что { b: 12345 } является объектом.

8). Идентичный вышеприведенный пример, но вместо точечной нотации, мы используем обозначение скобки.

9) Я уже говорил, что этот синтаксис "identifier: value" внутри оператора блока является меткой. Но вы также должны знать, что имя метки не может быть зарезервированным ключевым словом (напротив имен свойств объекта). Когда мы попытались определить метку с именем "true", мы получили SyntaxError.

10) Опять же, мы имеем дело с объектом. Здесь нет проблем с использованием зарезервированных слов. =)

11) Наконец, мы имеем следующее: !{}[true]

Разделите здесь вещи:

a) Делая отрицание, мы информируем синтаксический анализатор о том, что {} объект.

b) Как показано в примере 2, объект {} не имеет свойства с именем true, поэтому это выражение будет оцениваться как undefined.

c) Конечным результатом является отрицание undefinedстоимость. Javascript выполняет преобразование типа implicity и undefined Значение ложно.

d) Таким образом, отрицание false является... true!