{}[true]是[true]并且![true]应该是false。
那么为什么要 !{}[true]评估true呢?
{}[true] === [true]要从控制台获取,那是因为它被{}视为空代码块,而不是对象。
{},并({})在控制台(或{}[true]和({})[true])。同样,正如没有人提到的那样,object [true]被评估为object [“ true”]。
{}[true]是[true]并且![true]应该是false。
那么为什么要 !{}[true]评估true呢?
{}[true] === [true]要从控制台获取,那是因为它被{}视为空代码块,而不是对象。
{},并({})在控制台(或{}[true]和({})[true])。同样,正如没有人提到的那样,object [true]被评估为object [“ true”]。
Answers:
我认为这是因为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:
'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true
{}[true]在控制台中求值,则会得到[true],因为会{}被解释为空代码块,而不是对象。都是关于的上下文和含糊之处{}。
{key:"value"}[1,2,3];也要评估[1,2,3]?
key:)和字符串文字("value"),后跟数组。解析器仍然看不到对象文字。
alert()或中console.log(),或将其分配给变量,则将更改上下文,这就是为什么它的行为与在控制台中单独键入的行为不同的原因。
因为
{}[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
因此,没有矛盾。您可能正在使用旧版本的JavaScript VM。对于那些需要进一步证据的人:

使用Firefox时,其评估结果为true:

eval('{}[true]')或将其键入控制台,则不会。然后,例如als {}"test"是test,甚至{key:"value"}"test"是test。
{}[true];(和;)是否会[true]为您返回,因为在此返回?
造成混淆的原因是您对第一个主张的误解:
{}[true] 是 [true]
运行时所看到的是模棱两可的结果。JavaScript对于如何处理此类歧义性具有一组已定义的规则,在这种情况下,它会将您看到的signle语句分解为两个单独的语句。
因此,JavaScript将以上代码视为两个单独的语句:首先,有一个{},然后有一个完全分开的[true]。第二个陈述是给您结果的[true]。{}实际上,第一个陈述被完全忽略了。
您可以尝试以下方法证明这一点:
({}[true])
例如,将整个内容包装在方括号中,以迫使解释器将其作为单个语句读取。
现在,您将看到语句的实际值是undefined。(这也将有助于我们稍后理解下一部分)
现在我们知道您问题的开始部分是一条红鲱鱼,所以让我们进入问题的最后部分:
那么,为什么{{} [true]评估为true?
在这里,我们有相同的语句,但!在其前面附加了一个语句。
在这种情况下,Javascript的规则告诉它以单个语句来评估整个事物。
回顾一下我们将前面的语句放在方括号中时发生的情况;我们得到了undefined。这次,我们实际上在做相同的事情,但是要放在!前面。所以,你的代码可以作为简化!undefined,这是true。
希望这可以解释一下。
这是一个复杂的野兽,但是要在这里学习的课程是在控制台中评估语句时在语句周围使用方括号,以避免出现类似错误的结果。
{}[true]是无效的,只是模棱两可。可以解释为“空代码块后跟数组文字”或“没有属性的对象文字,正在访问其属性”。我不知道从技术上讲第一个是否是ASI(无论如何,许多语言都不会在其中添加分号),但这是上下文相关的解释是问题的核心。
{}[true]是true”,他们说“ {}[true]是[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使用表达式在对象上执行a 。表达式为:
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))= LogicalNOT(convertToBool(未定义))= LogicalNOT(false)= true({}['whatever']) =分组(NewObject.whatever)=分组(未定义)=未定义发生这种情况是因为{}您的意思不是的字面表示Object,而是空的作用域(或空的代码块):
{ var a = 1 }[true] // [true] (do the same thing)
它只是评估范围内的代码,然后向您显示数组。
从你的
!{}[true]
只是将这个范围转换为int并返回相同的数组true。此代码中没有布尔检查。
如果您尝试检查结果,{}[true]您将得到false:
{}[true] -> [true] -> ![true] -> false
由于没有任何范围。
因此,!在您的问题中,请执行以下操作:
!function() {
//...
}
var x = {}; x[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!")
显示两个警报。
因此,我们可以看到没有分号的空的block语句是有效的,并且什么也不做。这样,当您{}[true]在开发人员工具(或Firebug)控制台中输入时,评估值将是最后一个expression语句的值。在这种情况下,最后一个表达式语句是[true]。
2)在分配上下文中,解析器将确保这{}是一个对象文字。当执行var a =时{}[true],您消除了任何歧义,并提示了{}不是block语句的解析器。
因此,在这里,您尝试"true"从空对象获取带有键的值。显然,这个键名没有键值对。这样,a变量是不确定的。
ECMAScript 5允许对象键为保留字。因此,以下密钥是合法的:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3)与示例1相同的解释。但是...如果将该{ b: 12345 }零件视为一个块语句,该b: 12345语句的类型是什么?
...(??????)
这是一个标签声明,您之前已经看过了...在循环和循环中使用switch。以下是一些有关标签语句的有趣链接:1,(2)[ 打破Java嵌套循环的最佳方法?,(3)[ 如何打破javascript中的嵌套循环?。
注意:只需尝试评估此:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
标签语句不能用逗号分隔,您需要用分号将它们分开。所以这是有效的:{a: 1; b: 2}
4)参见示例1和3的说明 ...
5)再有一次,我们{ b: 12345 }被视为代码块,并且您正尝试使用点表示法来访问代码块的属性,显然,这是不允许的,并且解析器会引发"Unexpected token :"异常。
6)代码几乎与上面的示例相同,但是通过{ b: 12345 }用表达式分组运算符将语句包围起来,解析器将知道这是一个对象。这样,您将能够"b"正常访问该属性。
7)记住示例2,这里我们有一个赋值,解析器知道这{ b: 12345 }是一个对象。
9)我已经说过,"identifier: value"block语句中的这种语法是标签。但是,您还必须知道标签名称不能是保留关键字(与对象属性名称相反)。当我们尝试定义名为的标签时"true",我们得到了一个SyntaxError。
10)同样,我们正在处理一个对象。在这里使用保留字没有问题。=)
11)最后,我们有:!{}[true]
让我们在这里将它们分开:
a)通过否定,我们通知解析器the {}是一个object。
b)如示例2所示,{}对象没有名为的属性true,因此该表达式的计算结果为undefined。
c)最终结果是undefined价值否定。Javascript执行隐式类型转换,并且undefined值是falsy。
d)因此,否定false是... true!
var o = {}; o[true] === undefined。