[英]Why does !{}[true] evaluate to true in JavaScript?
{}[true]
is [true]
and ![true]
should be false
. {}[true]
是[true]
并且![true]
应该是false
。
So why does !{}[true]
evaluate to true
? 那么为什么
!{}[true]
评估为true
?
I believe that's because plain {}[true]
is parsed as an empty statement block (not an object literal) followed by an array containing true
, which is true
. 我相信这是因为plain
{}[true]
被解析为一个空语句块(不是对象文字),后跟一个包含true
的数组,这是true
。
On the other hand, applying the !
另一方面,申请
!
operator makes the parser interpret {}
as an object literal, so the following {}[true]
becomes a member access that returns undefined
, and !{}[true]
is indeed true
(as !undefined
is true
). 运算符使解析器将
{}
解释为对象文字,因此以下{}[true]
成为返回undefined
的成员访问,而!{}[true]
确实为true
(因为!undefined
为true
)。
Because {}[true]
does not return true
, but undefined
, and undefined
is evaluated as false
: 因为
{}[true]
不返回true
,但undefined
,并且undefined
被评估为false
:
http://jsfiddle.net/67GEu/ http://jsfiddle.net/67GEu/
'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true
Because 因为
{}[true]
evaluates to undefined
, and !undefined
is true
. 计算结果为
undefined
,并且!undefined
为true
。
From @schlingel: 来自@schlingel:
true
is used as key and {}
as hash map. true
用作键, {}
用作哈希映射。 There doesn't exist an property with the key true
so it returns undefined
. 不存在键为
true
的属性,因此返回undefined
。 Not undefined
is true
, as expected. 正如预期的那样,
undefined
是不true
。
Console session ( Node.js [0.10.17]
): 控制台会话( Node.js
[0.10.17]
):
> {}[true]
undefined
> !{}[true]
true
> [true]
[ true ]
> ![true]
false
>
However, in the Google Chrome console: 但是,在Google Chrome控制台中:
> !{}[true]
true
So, no inconsistencies. 所以,没有不一致。 You're probably using an old version of the JavaScript VM.
您可能正在使用旧版本的JavaScript VM。 For those who need further evidence:
对于那些需要进一步证据的人:
With Firefox , it also evaluates to true
: 使用Firefox ,它还评估为
true
:
The reason for the confusion is down to a misunderstanding of your first assertion: 造成混淆的原因可归结为对您的第一个断言的误解:
{}[true]
is [true]
{}[true]
是[true]
What you're seeing when you run it is the result of an ambiguity. 你运行它时所看到的是模棱两可的结果。 Javascript has a defined set of rules as to how to handle ambiguities like this, and in this case, it breaks what you see as a signle statement down into two separate statements.
Javascript有一套定义的规则来处理如何处理这样的歧义,在这种情况下,它会将你看到的signle语句分解为两个单独的语句。
So Javascript sees the above code as two separate statements: Firstly, there is a {}
, and then there is an entirely separate [true]
. 所以Javascript将上面的代码视为两个独立的语句:首先,有一个
{}
,然后有一个完全独立的[true]
。 The second statement is what is giving you the result [true]
. 第二个陈述是什么给你结果
[true]
。 The first statement {}
is effetively entirely ignored. 第一个陈述
{}
被有效地完全忽略了。
You can prove this by trying the following: 您可以通过尝试以下方法来证明这一点:
({}[true])
ie wrapping the whole thing in brackets to force the interpreter to read it as a single statement. 即将整个事物包装在括号中以强制解释器将其作为单个语句读取。
Now you'll see that the actual value of your statement is undefined
. 现在您将看到语句的实际值
undefined
。 (this will also help us later to understand the next part) (这也有助于我们以后了解下一部分)
Now we know that the initial part of your question is a red herring, so let's move onto the final part of the question: 现在我们知道问题的最初部分是红鲱鱼,所以让我们转到问题的最后部分:
So why does !{}[true] evaluate to true?
那么为什么!{} [true]评估为真?
Here, we have the same statement, but with a !
在这里,我们有相同的声明,但有一个
!
appended to the front of it. 附在前面。
In this case, Javascript's rules tell it to evaluates the entire thing as a single statement. 在这种情况下,Javascript的规则告诉它将整个事物评估为单个语句。
Refer back to what happened when we wrapped the earlier statement in brackets; 请回顾一下当我们用括号括起前面的陈述时发生的事情; we got
undefined
. 我们得到了
undefined
。 This time, we are effectively doing the same thing, but putting a !
这一次,我们有效地做同样的事情,但放一个
!
in front of it. 在它面前。 So your code can be simplified as
!undefined
, which is true
. 所以你的代码可以简化为
!undefined
,这是true
。
Hopefully that explains it a bit. 希望这能解释一下。
It is a complex beast, but the lesson to learn here is to use brackets around your statements when evaluating them in the console, to avoid spurious results like this. 这是一个复杂的野兽,但这里要学到的教训是在控制台中评估它们时使用括号括起来,以避免这样的虚假结果。
{}[true]
is undefined
. {}[true]
undefined
。 To find that write this: 要找到这样写:
a = {};
a[true] === undefined // true
or simply: 或者干脆:
({})[true] === undefined // true
We know that !undefined
is true
. 我们知道
!undefined
是true
。
From @Benjamin Gruenbaum's answer : 来自@Benjamin Gruenbaum的回答 :
Chrome dveloper tools does the following :
Chrome dveloper工具执行以下操作 :
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;
}
So basically, it performs a
call
on the object with the expression.所以基本上,它使用表达式对对象执行
call
。 The expression being:表达式为:
with ((window && window.console && window.console._commandLineAPI) || {}) {
{}+{};// <-- This is your code
}
So, as you can see, the expression is being evaluted directly, without the wrapping parenthesis.
因此,正如您所看到的,表达式是直接评估的,没有包装括号。
More information can be found in this question . 可以在此问题中找到更多信息。
The answers here are good, here's a breakdown in pseudo-code: 这里的答案很好,这里是伪代码的细分:
{}['whatever']
= empty block, NewArray('whatever') = NewArray('whatever') {}['whatever']
=空块,NewArray('whatever')= NewArray('what') {}[true]
= empty block, NewArray(true) = NewArray(true) {}[true]
=空块,NewArray(true)= NewArray(true) !{}['whatever']
= LogicalNOT(convertToBool(NewObject.whatever)) = LogicalNOT(convertToBool(undefined)) = LogicalNOT(false) = true !{}['whatever']
= LogicalNOT(convertToBool(NewObject.whatever))= LogicalNOT(convertToBool(undefined))= LogicalNOT(false)= true ({}['whatever'])
= Grouping(NewObject.whatever) = Grouping(undefined) = undefined ({}['whatever'])
=分组(NewObject.whatever)=分组(未定义)=未定义 This happens because {}
in your meaning is not literal presentation of Object
, but empty scope ( or empty code block ): 发生这种情况是因为你的意思中的
{}
不是Object
文字表示,而是空范围(或空代码块):
{ var a = 1 }[true] // [true] (do the same thing)
It just evaluates code inside scope and then shows you your array. 它只是评估范围内的代码,然后显示您的数组。
And from your 从你的
!{}[true]
Just converts to int this scope and return same array true. 只需将此范围转换为int并返回相同的数组即可。 There is no bool checks in this code.
此代码中没有bool检查。
And if you will try to check result from {}[true]
you will get your false
: 如果你试图检查
{}[true]
结果,你会得到你的false
:
{}[true] -> [true] -> ![true] -> false
As there is no more any scope. 因为没有任何范围。
So !
所以
!
in your question do the same as: 在你的问题中做同样的事情:
!function() {
//...
}
{}
is an object with no properties. {}
是一个没有属性的对象。 []
immediately follows an object, it means "Access a property of this name" and not "Create an array" []
紧跟在一个对象之后,它意味着“访问此名称的属性”而不是“创建一个数组” true
is a boolean, but is being used as an property name so it is cast to a string ( "true"
) true
是一个布尔值,但是被用作属性名称,因此它被强制转换为字符串( "true"
) true
(since it has no properties) so {}['true']
is undefined
true
的属性(因为它没有属性)所以{}['true']
是undefined
!undefined
casts undefined
to a boolean ( false
) !undefined
蒙上undefined
的布尔( false
) false
into true
. false
变为true
。 You're not reversing the value of it. 你没有扭转它的价值。
![true] != [!true]
Check this out: Why is !true ? 看看这个: 为什么是真的? 'false' : 'true' returning 'true'?
'false':'true'返回'true'?
First, let's have some fun!: 首先,让我们玩得开心!:
//----------#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) Here, the {}
is parsed as an empty code block. 1)这里,
{}
被解析为空代码块。 Without an assign, negation, grouping (with parentheses) or any syntax which indicates to the parser that this {}
is an object literal, the default assumption is to think it is simply a useless empty block. 如果没有赋值,否定,分组(带括号)或任何语法向解析器指示此
{}
是对象文字,则默认的假设是认为它只是一个无用的空块。
This is a proof of this behavior: 这是此行为的证明:
{ alert(123) }[true]
The code above will show the alert normally, and will be evaluated as [true]
, in the same way {}[true]
is. 上面的代码将正常显示警报,并将以
[true]
形式进行评估,其方式与{}[true]
相同。
A block-type statement doesn't need a semicolon after it. 块类型语句后面不需要分号。
For instance: 例如:
for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")
Both alerts are shown. 显示两个警报。
So, we can see that an empty block statement, without a semicolon, is valid and simply does nothing. 因此,我们可以看到没有分号的空块语句是有效的,并且什么都不做。 This way, when you enter
{}[true]
in the Developer Tools (or Firebug) Console, the evaluated value will be the value of the last expression statement . 这样,当您在Developer Tools(或Firebug)控制台中输入
{}[true]
时,评估的值将是最后一个表达式语句的值。 In this case, the last expression statement is [true]
. 在这种情况下,最后一个表达式语句是
[true]
。
2) In an assignment context, the parser will make sure that {}
is an object literal. 2)在赋值上下文中,解析器将确保
{}
是对象文字。 When you do var a = {}[true]
, you remove any ambiguity and tip the parser off that {}
is not a block statement. 当你执行var a =
{}[true]
,你会删除任何歧义并提示解析器{}
不是块语句。
So, here, you're trying to get a value with a key "true"
from an empty object. 所以,在这里,你试图从空对象中获取一个带有
"true"
键的值。 Obviously, there's no key-value pair with this key name. 显然,这个密钥名称没有键值对。 This way, the a variable is undefined.
这样,a变量是未定义的。
ECMAScript 5 allows object keys to be reserved words. ECMAScript 5允许对象键是保留字。 So, the following keys are legal:
因此,以下密钥是合法的:
var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}
3) The same explanation of example 1 . 3)与例1相同的解释。 But... If the
{ b: 12345 }
part is treated as a block statement, what's the type of the b: 12345
statement?? 但是......如果将
{ b: 12345 }
部分视为块语句,那么b: 12345
语句的类型是什么?
... (?????) ......(?????)
It's a label statement , you already saw it before... It's used in loops and in switch
. 这是一个标签声明 ,您之前已经看过它......它用于循环和
switch
。 Here are a few interesting links about label statements: 1 , (2)[ Best way to break from nested loops in Javascript? 以下是一些关于标签语句的有趣链接: 1 ,(2)[ 在Javascript中打破嵌套循环的最佳方法? , (3)[ How to break nested loops in javascript?
,(3)[ 如何在javascript中打破嵌套循环? .
。
NOTE: Just try to evaluate this: 注意:试着评估一下:
{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :
Label statements can't be separeted by the comma operator, you would need to separate them with a semicolon. 标签语句不能由逗号运算符分隔,您需要用分号分隔它们。 So this is valid:
{a: 1; b: 2}
所以这是有效的:
{a: 1; b: 2}
{a: 1; b: 2}
4) See the explanations for the examples 1 and 3 ... 4)参见实施例1和3的解释......
5) One more time, we have a { b: 12345 }
being treated as a code block, and you're trying to access a property of a code block by using the dot notation , and obviously, this is not allowed, and the parser throws an "Unexpected token :"
exception. 5)再一次,我们将
{ b: 12345 }
视为代码块,并且您尝试使用点表示法来访问代码块的属性,显然,这是不允许的,并且解析器抛出"Unexpected token :"
异常。
6) The code is almost identical to the above example, but by surrounding the { b: 12345 }
statement with the expression grouping operator , the parser will know that is an object. 6)代码几乎与上面的例子相同,但是通过用表达式分组运算符包围
{ b: 12345 }
语句,解析器将知道它是一个对象。 This way, you'll be able to access the "b"
property normally. 这样,您就可以正常访问
"b"
属性。
7) Remember the example 2 , we have an assignment here, the parser knows that { b: 12345 }
is an object. 7)记住示例2 ,我们在这里有一个赋值,解析器知道
{ b: 12345 }
是一个对象。
8) Identical to the above example, but instead of the dot notation, here we're using the bracket notation . 8)与上面的例子相同,但不是点符号,这里我们使用括号表示法 。
9) I already said that this "identifier: value"
syntax inside a block statement is a label. 9)我已经说过块语句中的这个
"identifier: value"
语法是一个标签。 But, you also have to know that a label name can't be a reserved keyword (the opposite of object property names). 但是,您还必须知道标签名称不能是保留关键字(与对象属性名称相反)。 When we tried to define a label called
"true"
, we got a SyntaxError
. 当我们尝试定义一个名为
"true"
的标签时,我们得到了一个SyntaxError
。
10) Again, we're dealing with an object. 10)同样,我们正在处理一个对象。 No problems using reserved words here.
这里使用保留字没问题。 =)
=)
11) Finally, we have this: !{}[true]
11)最后,我们有:
!{}[true]
Let's separate the things here: 让我们分开这里的事情:
a) By doing a negation, we're informing to the parser that the {}
is an object . a)通过做出否定,我们通知解析器
{}
是一个对象 。
b) As shown in the example 2 , a {}
object doesn't have a property called true
, so this expression will evaluate to undefined
. b)如示例2所示,
{}
对象没有名为true
的属性,因此该表达式将计算为undefined
。
c) The final result is the negation of undefined
value. c)最终结果是否定
undefined
值。 Javascript performs implicity type conversion , and undefined
value is falsy . Javascript执行隐含类型转换 ,
undefined
值是伪造的 。
d) So, the negation of false
is... true
! d)所以,对
false
的否定是...... true
!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.