{}[true]
ist [true]
und ![true]
sollte sein false
.
Warum also !{}[true]
auswerten zu true
?
Benutzer2430508
{}[true]
ist [true]
und ![true]
sollte sein false
.
Warum also !{}[true]
auswerten zu true
?
Frédéric Hamidi
Ich glaube, das liegt daran, schlicht {}[true]
wird als leerer Anweisungsblock (kein Objektliteral) geparst, gefolgt von einem Array, das enthält true
welches ist true
.
Andererseits wendet man die !
Operator lässt den Parser interpretieren {}
als Objektliteral, also das Folgende {}[true]
wird ein Mitgliedszugang, der zurückkehrt undefined
und !{}[true]
ist in der Tat true
(wie !undefined
ist true
).
Die Tatsache, dass !undefined wahr ist, ist dagegen immer noch unentschuldbar.
– böse Süßigkeitentüte
31. Oktober 2013 um 13:21 Uhr
@evilcandybag: Das ist es absolut nicht. undefined
ist falsch (etwas, worauf wir uns oft verlassen — if (obj.maybeExists) ...
), also macht es absolut logischen Sinn, dass !undefined
ist wahr.
– josh3736
31. Oktober 2013 um 14:24 Uhr
@Josh, ich denke, evilcandybag würde ein ähnliches Verhalten bevorzugen null
in manchen Sprachen mit !undefined
gleich sein undefined
. Bei Javascript ist das jedoch nicht der Fall.
– Frédéric Hamidi
31. Oktober 2013 um 14:28 Uhr
@evilcandybag: Es macht nur logischen Sinn zu sagen, dass etwas das ist not undefined
(!undefined
) muss daher definiert werden. Wenn etwas definiert ist, wird es normalerweise interpretiert als true
.
– OozeMeister
31. Oktober 2013 um 16:50 Uhr
@Cruncher Wenn a undefiniert ist und b undefiniert ist, wie können wir dann möglicherweise wissen, dass a! = b? Insbesondere dann, wenn die einzige bekannte Eigenschaft der beiden Variablen genau gleich ist.
– LJ2
31. Oktober 2013 um 18:15 Uhr
Da {}[true]
kehrt nicht zurück true
aber undefined
und undefined
wird bewertet als false
:
'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true
Wenn Sie bewerten {}[true]
in einer Konsole erhalten Sie [true]
weil die {}
wird als leerer Codeblock interpretiert, nicht als Objekt. Es geht um den Kontext und die Mehrdeutigkeit von {}
.
– IMSoP
31. Oktober 2013 um 9:45 Uhr
@IMSoP aber warum {key:"value"}[1,2,3];
auch auswerten [1,2,3]
?
– t.niese
31. Oktober 2013 um 9:52 Uhr
@t.niese, weil es als Anweisungsblock geparst wird, der ein Label enthält (key:
) und ein String-Literal ("value"
), gefolgt von einem Array. Der Parser sieht immer noch kein Objektliteral.
– Frédéric Hamidi
31. Oktober 2013 um 9:54 Uhr
@FrédéricHamidi ah ja, das ist es. Ich habe Etiketten unterdrückt ^^
– t.niese
31. Oktober 2013 um 9:56 Uhr
@dooxe Lesen Sie die anderen Antworten; es kommt auf den Kontext an, in dem es interpretiert wird. Wenn du es einpackst alert()
oder console.log()
oder weisen Sie es einer Variablen zu, ändern Sie den Kontext, weshalb es sich nicht so verhält, als ob es allein in einer Konsole eingegeben würde.
– IMSoP
31. Oktober 2013 um 10:14 Uhr
Spiele Brainiac
Da
{}[true]
wertet zu undefined
und !undefined
ist true
.
Von @schlingel:
true
wird als Schlüssel und verwendet {}
als Hashmap. Es gibt keine Eigenschaft mit dem Schlüssel true
also kehrt es zurück undefined
. Nicht undefined
ist true
wie erwartet.
Konsolensitzung (Node.js [0.10.17]
):
> {}[true]
undefined
> !{}[true]
true
> [true]
[ true ]
> ![true]
false
>
Allerdings im Google Chrome Konsole:
> !{}[true]
true
Also keine Ungereimtheiten. Sie verwenden wahrscheinlich eine alte Version der JavaScript-VM. Wer weitere Beweise braucht:
Mit Feuerfuchses wertet auch zu true
:
Nicht, wenn du es tust eval('{}[true]')
oder geben Sie es in die Konsole ein. Dann zB als {}"test"
ist test
oder auch {key:"value"}"test"
ist test
.
– t.niese
31. Oktober 2013 um 9:42 Uhr
Interessant, in welcher js-Engine testest du das?
– t.niese
31. Oktober 2013 um 9:45 Uhr
@t.niese Ich habe es gerade in meine Knotenkonsole eingegeben und das habe ich bekommen.
– Spiele Brainiac
31. Oktober 2013 um 9:45 Uhr
Nur aus Neugier. Tut {}[true];
(mit dem ;
) Rückkehr [true]
für dich, denn hier tut es ?
– t.niese
31. Oktober 2013 um 9:46 Uhr
Grund für Downvote Jungs? Da ist ein fast identische Antwort auf diese mit 8 Stimmen, und ich bekomme die Ablehnung? Was habe ich falsch gemacht?
– Spiele Brainiac
31. Oktober 2013 um 9:48 Uhr
Spudley
Der Grund für die Verwirrung liegt in einem Missverständnis Ihrer ersten Behauptung:
{}[true]
ist [true]
Was Sie sehen, wenn Sie es ausführen, ist das Ergebnis einer Mehrdeutigkeit. Javascript hat einen definierten Satz von Regeln, wie mit solchen Mehrdeutigkeiten umzugehen ist, und in diesem Fall zerlegt es das, was Sie als signle-Anweisung sehen, in zwei separate Anweisungen.
Javascript sieht den obigen Code also als zwei separate Anweisungen: Erstens gibt es eine {}
und dann gibt es noch eine ganz andere [true]
. Die zweite Anweisung gibt Ihnen das Ergebnis [true]
. Die erste Aussage {}
wird effektiv völlig ignoriert.
Sie können dies beweisen, indem Sie Folgendes versuchen:
({}[true])
dh das Ganze in Klammern einzuschließen, um den Interpreter zu zwingen, es als eine einzige Anweisung zu lesen.
Jetzt sehen Sie, dass der eigentliche Wert Ihrer Aussage 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 Ablenkungsmanöver ist, also kommen wir zum letzten Teil der Frage:
Warum also !{}[true] als wahr bewerten?
Hier haben wir die gleiche Aussage, aber mit a !
davor angehängt.
In diesem Fall werten die Regeln von Javascript das Ganze als eine einzige Anweisung aus.
Beziehen Sie sich auf das, was passiert ist, als wir die frühere Aussage in Klammern gesetzt haben; wir haben undefined
. Diesmal tun wir effektiv dasselbe, setzen aber a !
vor. So kann Ihr Code vereinfacht werden als !undefined
welches ist true
.
Das erklärt es hoffentlich ein wenig.
Es ist ein komplexes Tier, aber die Lektion, die Sie hier lernen sollten, ist, Ihre Aussagen in Klammern zu setzen, wenn Sie sie in der Konsole auswerten, um solche falschen Ergebnisse zu vermeiden.
Ionica Bizau
{}[true]
ist undefined
. Um das zu finden, schreiben Sie Folgendes:
a = {};
a[true] === undefined // true
oder einfach:
({})[true] === undefined // true
Wir wissen das !undefined
ist true
.
Aus der Antwort von @Benjamin Gruenbaum:
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;
}
Also im Grunde führt es a
call
auf das Objekt mit dem Ausdruck. Der Ausdruck lautet:
with ((window && window.console && window.console._commandLineAPI) || {}) {
{}+{};// <-- This is your code
}
Wie Sie sehen können, wird der Ausdruck also direkt ohne die umschließende Klammer ausgewertet.
Weitere Informationen finden Sie in dieser Frage.
Frédéric Hamidi
Die Antworten hier sind gut, hier ist eine Aufschlüsselung im Pseudocode:
{}['whatever']
= leerer Block, NewArray(‘whatever’) = NewArray(‘whatever’){}[true]
= leerer Block, NewArray(true) = NewArray(true)!{}['whatever']
= LogicalNOT(convertToBool(NewObject.whatever)) = LogicalNOT(convertToBool(undefined)) = LogicalNOT(false) = true({}['whatever'])
= Gruppierung (NewObject.whatever) = Gruppierung (undefiniert) = undefiniertDies geschieht, weil {}
in Ihrem Sinne ist keine wörtliche Darstellung von Object
aber leerer Gültigkeitsbereich ( oder leerer Codeblock ):
{ var a = 1 }[true] // [true] (do the same thing)
Es wertet nur den Code innerhalb des Gültigkeitsbereichs aus und zeigt Ihnen dann Ihr Array.
Und von Ihrem
!{}[true]
Konvertiert diesen Bereich einfach in int und gibt dasselbe Array true zurück. In diesem Code gibt es keine booleschen Prüfungen.
Und wenn Sie versuchen, das Ergebnis zu überprüfen {}[true]
du wirst deine bekommen false
:
{}[true] -> [true] -> ![true] -> false
Da gibt es keinen Spielraum mehr.
So !
In Ihrer Frage tun Sie dasselbe wie:
!function() {
//...
}
Dies ist leichter zu sehen, wenn Sie dies tun var x = {}; x[true]
.
– Chris Hayes
31. Oktober 2013 um 9:43 Uhr
Ich bin mir nicht sicher, was Sie mit “konvertiert diesen Bereich int” meinen; Ich denke mit der Führung !
es ist als leeres Objekt interpretiert, nicht als Bereich, und das ist die Diskrepanz.
– IMSoP
31. Oktober 2013 um 9:43 Uhr
var o = {}; o[true] === undefined
.– azz
31. Oktober 2013 um 9:39 Uhr
Die Erklärung hier wird wahrscheinlich den Kuriositäten sehr ähnlich sein, die bei dieser vorherigen Frage besprochen wurden
– IMSoP
31. Oktober 2013 um 9:40 Uhr
„Weil Javascript albern ist“ ist wahrscheinlich nicht die Antwort, die Sie suchen.
– georg
31. Oktober 2013 um 9:44 Uhr
Wie gesagt, wenn du es bekommst
{}[true] === [true]
von einer Konsole, das liegt daran, dass es behandelt wird{}
als leerer Codeblock, kein Objekt.– azz
31. Oktober 2013 um 9:48 Uhr
Wenn es hilft, versuchen Sie zu vergleichen
{}
und({})
in deiner Konsole (bzw{}[true]
und({})[true]
). Auch, da niemand es erwähnt hat, Einspruch[true] wird zum Einwand ausgewertet[“true”].– BiAiB
31. Oktober 2013 um 12:28 Uhr