{}[true]
[true]
и ![true]
должен быть false
.
Итак, почему !{}[true]
оценивается на true
?
{}[true]
[true]
и ![true]
должен быть false
.
Итак, почему !{}[true]
оценивается на true
?
Я считаю, что, поскольку plain {}[true]
анализируется как пустой операторный блок (а не литерал объекта), за которым следует массив, содержащий true
, который является true
.
С другой стороны, применение оператора !
делает синтаксический анализатор интерпретирует {}
как литерал объекта, поэтому следующий {}[true]
становится членом доступа, который возвращает undefined
, а !{}[true]
действительно true
> (как !undefined
есть true
).
Поскольку {}[true]
не возвращает true
, но undefined
и undefined
оценивается как false
:
'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true
Поскольку
{}[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. Для тех, кто нуждается в дополнительных доказательствах:
С Firefox он также оценивает true
:
Причина путаницы сводится к непониманию вашего первого утверждения:
{}[true]
[true]
То, что вы видите при запуске, является результатом двусмысленности. Javascript имеет определенный набор правил относительно того, как обрабатывать двусмысленности, подобные этому, и в этом случае он разбивает то, что вы видите как оператор signle, на два отдельных оператора.
Итак, Javascript видит вышеуказанный код как два отдельных оператора: во-первых, существует {}
, а затем есть полностью отдельный [true]
. Второе утверждение - это то, что дает вам результат [true]
. Первое утверждение {}
полностью игнорируется.
Вы можете доказать это, попробовав следующее:
({}[true])
т.е. обернуть все это в скобках, чтобы заставить интерпретатор читать его как единый оператор.
Теперь вы увидите, что фактическое значение вашего оператора undefined
. (это также поможет нам позже понять следующую часть)
Теперь мы знаем, что начальная часть вашего вопроса - красная селедка, поэтому давайте перейдем к заключительной части вопроса:
Итак, почему? {} [true] оценивает true?
Здесь мы имеем то же утверждение, но с !
, добавленным к нему.
В этом случае правила Javascript говорят, что он оценивает всю вещь как единый оператор.
Обратитесь к тому, что произошло, когда мы завернули предыдущий оператор в скобках; мы получили undefined
. На этот раз мы делаем то же самое, но ставим перед ним !
. Таким образом, ваш код можно упростить как !undefined
, который true
.
Надеюсь, это немного объяснит.
Это сложный зверь, но урок для изучения здесь - использовать скобки вокруг своих утверждений при оценке их в консоли, чтобы избежать ложных результатов, подобных этому.
{}[true]
undefined
. Найти это:
a = {};
a[true] === undefined // true
или просто:
({})[true] === undefined // true
Мы знаем, что !undefined
true
.
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
}
Итак, как вы можете видеть, выражение вычисляется напрямую, без скобок.
Более подробную информацию можно найти в этом вопросе.
Ответ здесь хорош, здесь разбивка на псевдокод:
{}['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Это происходит потому, что {}
в вашем значении не является литеральным представлением Object
, а пустой областью (или пустым блоком кода):
{ var a = 1 }[true] // [true] (do the same thing)
Он просто оценивает код внутри области видимости и показывает ваш массив.
И из вашего
!{}[true]
Просто преобразует в int эту область и возвращает тот же самый массив true. В этом коде нет проверок bool.
И если вы попытаетесь проверить результат с {}[true]
, вы получите свой false
:
{}[true] -> [true] -> ![true] -> false
Поскольку больше нет области видимости.
Итак !
в вашем вопросе сделайте то же самое, что:
!function() {
//...
}
{}
- объект без свойств.[]
сразу следует за объектом, это означает "Доступ к свойству этого имени", а не "Создать массив" true
является логическим, но используется как имя свойства, поэтому он передается в строку ("true"
)true
(поскольку он не имеет свойств), поэтому {}['true']
есть undefined
!undefined
добавляет undefined
в булевское (false
)false
в true
.Вы не меняете его значение.
![true] != [!true]
Проверьте это: Почему это правда? "false" : "true" , возвращающий "true" ?
Во-первых, пусть будет весело!:
//----------#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
!