{}[true]
ist [true]
und ![true]
soll sein false
.
Warum also !{}[true]
bewerten true
?
javascript
user2430508
quelle
quelle
var o = {}; o[true] === undefined
.{}[true] === [true]
eine Konsole{}
als leerer Codeblock und nicht als Objekt behandelt.{}
und({})
in Ihrer Konsole (oder{}[true]
und({})[true]
) zu vergleichen . Wie niemand es erwähnt hat, wird das Objekt [wahr] als Objekt ["wahr"] ausgewertet.Antworten:
Ich glaube, das
{}[true]
liegt daran, dass plain als leerer Anweisungsblock (kein Objektliteral) analysiert wird, gefolgt von einem Array, das enthälttrue
, dastrue
:Wenn Sie jedoch den
!
Operator anwenden , wird der Parser{}
als Objektliteral interpretiert , sodass das Folgende{}[true]
zu einem Elementzugriff wird, der zurückkehrtundefined
und!{}[true]
tatsächlichtrue
(wie er!undefined
isttrue
) ist.quelle
undefined
ist falsch (etwas, auf das wir uns oft verlassen -if (obj.maybeExists) ...
), also macht es vollkommen logisch Sinn, dass!undefined
es wahr ist.null
in einigen Sprachen ähnlich!undefined
ist und gleich istundefined
. Dies ist in Javascript jedoch nicht der Fall.not undefined
(!undefined
) ist, daher definiert werden muss. Wenn etwas definiert ist, wird es normalerweise als interpretierttrue
.Weil
{}[true]
nicht zurückgibttrue
, sondernundefined
undundefined
ausgewertet wird alsfalse
:http://jsfiddle.net/67GEu/
quelle
{}[true]
in einer Konsole auswerten , erhalten Sie[true]
, weil der{}
als leerer Codeblock interpretiert wird, nicht als Objekt. Es geht um den Kontext und die Mehrdeutigkeit von{}
.{key:"value"}[1,2,3];
auch ausgewertet[1,2,3]
?key:
) und ein Zeichenfolgenliteral ("value"
) enthält, gefolgt von einem Array. Der Parser sieht immer noch kein Objektliteral.alert()
oder umschließen oderconsole.log()
einer Variablen zuweisen, ändern Sie den Kontext, weshalb es sich nicht so verhält, wie es allein in einer Konsole eingegeben wurde.weil
bewertet zu
undefined
und!undefined
isttrue
.Von @schlingel:
true
wird als Schlüssel und{}
als Hash-Map verwendet. Es gibt keine Eigenschaft mit dem Schlüssel,true
daher wird dieser zurückgegebenundefined
. Nichtundefined
isttrue
, wie erwartet.Konsolensitzung ( Node.js
[0.10.17]
):In der Google Chrome- Konsole:
Also keine Inkonsistenzen. Sie verwenden wahrscheinlich eine alte Version der JavaScript-VM. Für diejenigen, die weitere Beweise benötigen:
AKTUALISIEREN
Mit Firefox wird außerdem Folgendes ausgewertet
true
:quelle
eval('{}[true]')
oder in die Konsole eingeben. Dann zB als{}"test"
isttest
oder sogar{key:"value"}"test"
isttest
.{}[true];
(mit dem;
)[true]
für dich zurück, weil es hier tut?Der Grund für die Verwirrung liegt in einem Missverständnis Ihrer ersten Behauptung:
{}[true]
ist[true]
Was Sie beim Ausführen sehen, ist das Ergebnis einer Mehrdeutigkeit. Javascript verfügt über definierte Regeln für den Umgang mit solchen Mehrdeutigkeiten. In diesem Fall wird das, was Sie als Signle-Anweisung betrachten, in zwei separate Anweisungen unterteilt.
Javascript sieht den obigen Code also als zwei separate Anweisungen: Erstens gibt es eine
{}
und dann eine völlig separate[true]
. Die zweite Aussage gibt Ihnen das Ergebnis[true]
. Die erste Aussage{}
wird praktisch vollständig ignoriert.Sie können dies beweisen, indem Sie Folgendes versuchen:
dh das Ganze in Klammern setzen, um den Interpreter zu zwingen, es als einzelne Anweisung zu lesen.
Jetzt sehen Sie, dass der tatsächliche Wert Ihrer Anweisung ist
undefined
. (Dies wird uns später auch helfen, den nächsten Teil zu verstehen.)Jetzt wissen wir, dass der erste Teil Ihrer Frage ein roter Hering ist. Gehen wir also zum letzten Teil der Frage über:
Hier haben wir die gleiche Aussage, aber mit einem
!
an die Vorderseite angehängten.In diesem Fall schreiben die Regeln von Javascript vor, dass das Ganze als einzelne Anweisung bewertet werden soll.
Verweisen Sie auf das, was passiert ist, als wir die frühere Aussage in Klammern gesetzt haben. wir haben
undefined
. Dieses Mal machen wir effektiv das Gleiche, stellen aber ein!
davor. So kann Ihr Code wie!undefined
folgt vereinfacht werdentrue
.Hoffentlich erklärt das ein bisschen.
Es ist ein komplexes Tier, aber die Lektion, die Sie hier lernen müssen, besteht darin, bei der Auswertung in der Konsole Klammern um Ihre Aussagen zu verwenden, um solche falschen Ergebnisse zu vermeiden.
quelle
{}[true]
es genau ungültig ist , nur mehrdeutig . Es kann entweder als "leerer Codeblock gefolgt von einem Array-Literal" oder als "Objektliteral ohne Eigenschaften, auf die auf eine Eigenschaft zugegriffen wird" interpretiert werden. Ich weiß nicht, ob es sich bei der ersten technisch um ASI handelt (viele Sprachen würden dort sowieso kein Semikolon einfügen), aber es ist die kontextsensitive Interpretation, die das Herzstück des Problems darstellt.{}[true]
isttrue
" gesagt, sondern "{}[true]
ist[true]
", was eine der beiden gültigen Interpretationen der mehrdeutigen Aussage ist.{}[true]
istundefined
. Um das zu finden, schreiben Sie Folgendes:oder einfach:
Wir wissen , dass
!undefined
isttrue
.Aus der Antwort von @Benjamin Gruenbaum :
Weitere Informationen finden Sie in dieser Frage .
quelle
Die Antworten hier sind gut, hier ist eine Aufschlüsselung des Pseudocodes:
{}['whatever']
= leerer Block, NewArray ('was auch immer') = NewArray ('was auch immer'){}[true]
= leerer Block, NewArray (true) = NewArray (true)!{}['whatever']
= LogicalNOT (convertToBool (NewObject.whatever)) = LogicalNOT (convertToBool (undefiniert)) = LogicalNOT (false) = true({}['whatever'])
= Gruppierung (NewObject.whatever) = Gruppierung (undefiniert) = undefiniertquelle
Dies geschieht, weil
{}
in Ihrer Bedeutung nicht wörtliche DarstellungObject
, sondern leerer Bereich (oder leerer Codeblock) ist:Es wertet nur den Code innerhalb des Gültigkeitsbereichs aus und zeigt Ihnen dann Ihr Array.
Und von deinem
Konvertiert einfach in diesen Bereich und gibt dasselbe Array true zurück. In diesem Code gibt es keine Bool-Prüfungen.
Und wenn Sie versuchen, das Ergebnis zu überprüfen, erhalten
{}[true]
Sie Folgendesfalse
:Da gibt es keinen Spielraum mehr.
Machen Sie
!
in Ihrer Frage dasselbe wie:quelle
var x = {}; x[true]
.!
es wird als ein leeres Objekt interpretiert, nicht Umfang, und dies ist die Diskrepanz.{}
ist ein Objekt ohne Eigenschaften.[]
unmittelbar auf ein Objekt folgt, bedeutet dies "Zugriff auf eine Eigenschaft dieses Namens" und nicht "Array erstellen".true
ist ein Boolescher Wert, wird jedoch als Eigenschaftsname verwendet, sodass er in einen String umgewandelt wird ("true"
)true
(da es keine Eigenschaften hat) , so{}['true']
istundefined
!undefined
Castsundefined
zu einem Booleschen Wert (false
)false
zutrue
.quelle
{}[true]
(ohne anderen Kontext){}
handelt es sich nicht um ein Objekt ohne Eigenschaften, sondern um einen leeren Codeblock.Sie kehren den Wert nicht um.
Schauen Sie sich das an: Warum ist! Wahr? 'false': 'true' gibt 'true' zurück?
quelle
Lass uns ein bisschen mehr spielen!
Lass uns zuerst ein bisschen Spaß haben!:
Ok, lass uns versuchen, diese verrückten Verhaltensweisen einzeln zu verstehen:
1) Hier wird das
{}
als leerer Codeblock analysiert. Ohne Zuweisung, Negation, Gruppierung (mit Klammern) oder einer Syntax, die dem Parser anzeigt, dass dies{}
ein Objektliteral ist, wird standardmäßig angenommen, dass es sich einfach um einen nutzlosen leeren Block handelt.Dies ist ein Beweis für dieses Verhalten:
Der obige Code zeigt die Warnung normalerweise, und wie bewertet wird
[true]
, in der gleichen Art und Weise{}[true]
ist.Blockanweisungen ohne Semikolons
Eine blockartige Anweisung benötigt danach kein Semikolon.
Zum Beispiel:
Beide Warnungen werden angezeigt.
Wir können also sehen, dass eine leere Blockanweisung ohne Semikolon gültig ist und einfach nichts bewirkt. Auf diese Weise ist
{}[true]
der ausgewertete Wert beim Aufrufen der Developer Tools (oder Firebug) -Konsole der Wert der letzten Ausdrucksanweisung . In diesem Fall lautet die letzte Ausdrucksanweisung[true]
.2) In einem Zuweisungskontext stellt der Parser sicher, dass
{}
es sich um ein Objektliteral handelt. Wenn Sie var a ={}[true]
ausführen, entfernen Sie alle Mehrdeutigkeiten und geben dem Parser{}
einen Hinweis , der keine Blockanweisung ist.Hier versuchen Sie also, mit einem Schlüssel einen Wert zu erhalten
"true"
von einem leeren Objekt abzurufen. Offensichtlich gibt es kein Schlüssel-Wert-Paar mit diesem Schlüsselnamen. Auf diese Weise ist die Variable a undefiniert.Reservierte Wörter als Objektschlüssel
Mit ECMAScript 5 können Objektschlüssel reservierte Wörter sein. Die folgenden Schlüssel sind also legal:
3) Die gleiche Erklärung von Beispiel 1 . Aber ... Wenn das
{ b: 12345 }
Teil als Blockanweisung behandelt wird, wie lautet die Art derb: 12345
Anweisung?... (?????)
Es ist eine Label-Anweisung , die Sie bereits gesehen haben ... Sie wird in Loops und in verwendet
switch
. Hier sind einige interessante Links zu Label-Anweisungen: 1 , (2) [Der beste Weg, um aus verschachtelten Schleifen in Javascript auszubrechen? , (3) [ Wie werden verschachtelte Schleifen in Javascript unterbrochen? .HINWEIS: Versuchen Sie einfach, dies zu bewerten:
Label-Anweisungen können vom Komma- Operator nicht getrennt werden. Sie müssen sie mit einem Semikolon trennen. Das ist also gültig:
{a: 1; b: 2}
4) Siehe die Erläuterungen zu den Beispielen 1 und 3 ...
5) Noch einmal, wir werden
{ b: 12345 }
als Codeblock behandelt, und Sie versuchen, mithilfe der Punktnotation auf eine Eigenschaft eines Codeblocks zuzugreifen. Dies ist natürlich nicht zulässig, und der Parser löst eine"Unexpected token :"
Ausnahme aus.6) Der Code ist fast identisch mit dem obigen Beispiel, aber durch Umgeben der
{ b: 12345 }
Anweisung mit dem Ausdrucksgruppierungsoperator weiß der Parser, dass es sich um ein Objekt handelt. Auf diese Weise können Sie"b"
normal auf die Unterkunft zugreifen .7) Denken Sie an Beispiel 2 , wir haben hier eine Zuordnung, der Parser weiß, dass
{ b: 12345 }
es sich um ein Objekt handelt.8) Identisch mit dem obigen Beispiel, aber anstelle der Punktnotation verwenden wir hier die Klammernotation .
9) Ich habe bereits gesagt, dass diese
"identifier: value"
Syntax in einer Blockanweisung eine Bezeichnung ist. Sie müssen jedoch auch wissen, dass ein Labelname kein reserviertes Schlüsselwort sein kann (das Gegenteil von Objekteigenschaftsnamen). Als wir versuchten, ein Label namens zu definieren"true"
, bekamen wir einSyntaxError
.10) Wir haben es wieder mit einem Objekt zu tun. Keine Probleme mit reservierten Wörtern hier. =)
11) Schließlich haben wir Folgendes:
!{}[true]
Lassen Sie uns die Dinge hier trennen:
a) Durch eine Negation informieren wir den Parser, dass
{}
es sich um ein Objekt handelt .b) Wie in Beispiel 2 gezeigt , hat ein
{}
Objekt keine aufgerufene Eigenschafttrue
, daher wird dieser Ausdruck als ausgewertetundefined
.c) Das Endergebnis ist die Negation des
undefined
Wertes. Javascript führt eine Konvertierung des Implizitätstyps durch , und derundefined
Wert ist falsch .d) Die Negation von
false
ist also ...true
!quelle