Warum tut !{}[true] in JavaScript auf true auswerten?

Lesezeit: 7 Minuten

Benutzer-Avatar
Benutzer2430508

{}[true] ist [true] und ![true] sollte sein false.

Warum also !{}[true] auswerten zu true?

  • 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

Benutzer-Avatar
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 truewelches ist true.

Andererseits wendet man die ! Operator lässt den Parser interpretieren {} als Objektliteral, also das Folgende {}[true] wird ein Mitgliedszugang, der zurückkehrt undefinedund !{}[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 trueaber undefinedund undefined wird bewertet als false:

http://jsfiddle.net/67GEu/

'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


Benutzer-Avatar
Spiele Brainiac

Da

{}[true]

wertet zu undefinedund !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 truewie 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:

Geben Sie hier die Bildbeschreibung ein

AKTUALISIEREN

Mit Feuerfuchses wertet auch zu true:

Geben Sie hier die Bildbeschreibung ein

  • 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


Benutzer-Avatar
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 !undefinedwelches 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.

Benutzer-Avatar
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:

Chrome-Entwicklertools tun Folgendes:

  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.

Benutzer-Avatar
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) = undefiniert

Dies geschieht, weil {} in Ihrem Sinne ist keine wörtliche Darstellung von Objectaber 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

1252670cookie-checkWarum tut !{}[true] in JavaScript auf true auswerten?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy