Warum ist {} + {} in der Chrome-Konsole nicht mehr NaN?

144

Ich habe heute festgestellt, dass Chrome 49 NaNbeim Eingeben {}+{}in die Konsole nicht mehr ausgegeben wird . Stattdessen wird die Zeichenfolge ausgegeben [object Object][object Object].

Warum ist das? Hat sich die Sprache geändert?

Filip Haglund
quelle
13
Es sieht so aus, als würde Chrome diesen Vorgang jetzt eher als String-Concat als als Addition behandeln. WARUM das ist, ich weiß nicht, weshalb dies ein Kommentar ist, keine Antwort :) Versuchen var e = {}; e.toString()Sie und Sie werden sehen, was ich meine
user428517
19
"Hat sich die Sprache geändert?" Nein
Felix Kling
6
@FelixKling Wird sich die Sprache ändern? ...Nein. : c
Katze
18
Vielleicht hatte WATMAN etwas damit zu tun?
Rickster
1
@rickster so habe ich es gefunden. Ich habe das für eine Präsentation neu erstellt.
Filip Haglund

Antworten:

152

Chrome devtools packt jetzt automatisch alles, was mit beginnt {und endet, }in ein implizites Klammerpaar ( siehe Code ), um die Auswertung als Ausdruck zu erzwingen. Auf diese Weise wird {}jetzt ein leeres Objekt erstellt. Sie können dies sehen, wenn Sie den Verlauf ( ) durchgehen , in dem die vorherige Zeile enthalten ist (…).

Warum? Ich weiß es nicht, aber ich könnte vermuten, dass es die Verwirrung für Neulinge verringert, die das Block-gegen-Objekt-Literal-Ding nicht kennen, und es ist auch hilfreicher, wenn Sie nur einen Ausdruck bewerten möchten.

Und tatsächlich ist dies die Begründung, wie in Fehler 499864 beschrieben . Komfort pur. Und weil der Knoten REPL es auch hatte ( siehe Code ).

Bergi
quelle
182
Dummes Chrome, {a:1}),({b:2}sollte einen Fehler auslösen, kein Objekt erzeugen.
Oriol
29
Das ist, was passiert, wenn Sie willkürlich tief verschachtelte Strukturen mit Regex Stackoverflow.com/questions/1732348/…
Filip Haglund
4
Ich habe keine Ahnung warum, aber irgendwie fühle ich mich "berühmt", wenn ich meine Nachrichten dort sehe, obwohl diese Seite genauso öffentlich ist wie diese: D Weird StackOverflow Problem. Hier ist meine ältere Antwort über das Problem stackoverflow.com/questions/17268468/…
Benjamin Gruenbaum
3
Ich mag die aktuelle Implementierung nicht und plane, sie zu beheben. bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak
1
@ Zirak Viel Glück beim Reparieren dieses Mülls, IMO sollte es so schnell wie möglich zurückgesetzt werden. Wenn Sie es jedoch verbessern möchten, sollten Sie vor dem Einfügen eine neue Zeile hinzufügen, )falls es sich um einen Kommentar handelt, z. B. {a:3} // :-}möglicherweise immer noch ein Objekt.
Oriol
44

Wenn Sie nach dem Überprüfen auf den Aufwärtspfeil klicken, werden Sie feststellen, dass stattdessen der Pfeil nach oben {} + {}angezeigt ({} + {})wird "[object Object][object Object]".

Im Vergleich dazu wird in Firefox {} + {}immer noch angezeigt NaN, aber wenn Sie dies tun, wird ({} + {})es auch angezeigt "[object Object][object Object]".

Es sieht also so aus, als würde Chrome die umgebende Klammer automatisch hinzufügen, wenn dieser Vorgang angezeigt wird.

J. Titus
quelle
22
Diese Antwort ist richtig. Aber wow, Mann, ich bin mir nicht sicher, ob ich das mag. Chrom macht das. schlechtes Google.
user428517
1
@sgroves Es würde mich interessieren, ob dies auf Canary dasselbe ist und ob es absichtlich gemacht wurde oder tatsächlich ein Fehler ist.
J. Titus
8
{} + {}Wenn nicht "bereinigt", ({} + {})wird behandelt, + {}weil {}es als leerer Block analysiert wird.
Gregory Nisbet
7
Warum sollte es überhaupt NaN zurückgeben?
0x499602D2
25
@ 0x499602D2: Denn wenn Sie nicht die Parens ausführen (oder den Parser auf andere Weise veranlassen, einen Ausdruck anstelle einer Anweisung zu erwarten), ist die Initiale {}nur ein leerer Codeblock und wird ignoriert, sodass wir +{}ein unäres +und ein leeres Objekt haben Initialisierer. +wird sein Argument in Zahl zwingen, was das Konvertieren des Objekts in ein Grundelement beinhaltet (was toStringin diesem Fall zu einem führt, was dazu führt "[object Object]"), und so erhalten wir, +"[object Object]"was daran liegt, NaNdass "[object Object]"es nicht in eine gültige Zahl konvertiert werden kann.
TJ Crowder
4

Ab Chrome 54 in Bezug auf die Konsole:

📎- "Ich habe diesen Block für Sie in ein Objekt konvertiert" -Clippy Leider habe ich das Clippy-Zitat selbst hinzugefügt. Die Konsole gibt keine Informationen darüber, was sie für Sie getan hat.

Die neuen Regeln sind unglaublich einfach und ersparen uns die Mühe, diese beiden schwierigen Zeichen mühsam einzugeben o=oder Objektliterale 0,in die Konsole einzufügen :

  • Wenn Sie Code haben, der beginnt mit: optionalem Leerzeichen (keine Kommentare zulässig), gefolgt von a {;
  • und dieser Code könnte als Objekt interpretiert werden;
  • und diesem Objekt folgt kein anderer Code, es sei denn:
  • Der Code nach dem ersten Objekt ist ein binärer Operator.
  • Dann kann es so viele Operationen geben, wie Sie möchten, einschließlich Gruppierungen
  • vorausgesetzt, der Endoperator hat ein Objektliteral in der rechten Position;
  • und dieses letzte Objekt wurde nicht in Parens gruppiert
  • und dieser Code wird nicht mit einem Semikolon abgeschlossen
  • und es folgen keine Kommentare nach dem Code (interne Kommentare sind zulässig, solange sie sich nicht an der Anfangs- oder Endposition befinden).
  • dann und nur dann wird Ihr JavaScript (das möglicherweise tatsächlich gültiger Code ist oder nicht) als gültiges Objekt wieder aufgenommen. Sie werden nicht darüber informiert, dass Ihr Code neu interpretiert wurde.

{wat:1}),({wat:2} Ist endlich wieder ein Fehler.

{let i=0;var increment=_=>i++} ist endlich richtig erlaubt, was eine ganz nette Art ist, Verschlüsse zu machen.

Das Folgende ist jedoch fälschlicherweise ein Objekt. Dies ist genauso praktisch wie von @Bergi erwähnt. Es interpretiert JS falsch, um Ihnen zu helfen! Die Spezifikation besagt, dass es sich um einen Block mit einer beschrifteten Anweisung "foo" mit einem Literal 1 handelt, der nichts zugewiesen ist.

{foo:1}

Das obige sollte das gleiche sein wie

if(1) {
    foo: 1
}

Das Folgende wird korrekt als Block behandelt ... weil es einen Kommentar vor sich hat!

//magic comment
{foo:1}

Also das ist:

{foo:1}
//also magic

Dies ist ein Objekt:

{foo:
//not so magic comment
1}

Dies ist ein Fehler

//not so magic comment
{foo:1}.foo

Also das ist:

{foo:1}.foo

Das ist in Ordnung:

1..wat

undefined

also das ist:

['foo'][0]

Das nächste wird korrekt als ein Objekt interpretiert, das mit einem in die Ausdrucksposition geschlagen 0,wird. Auf diese Weise stellen wir im Allgemeinen eindeutig sicher, dass wir einen Ausdruck anstelle einer Anweisung haben.

0,{foo:1}.foo

Ich verstehe nicht, warum sie den Wert in Parens einwickeln. JS hat einige lächerliche Designentscheidungen, aber der Versuch, es in dieser einen Situation besser zu machen, ist keine Option. Die Konsole muss JS korrekt ausführen, und wir müssen sicher sein, dass Chrome nicht nur vermutet, dass es uns denkt meinte es wirklich, etwas anderes zu tun.

Wenn Sie keine Kommaoperatoren mögen, können Sie die Zuweisung verwenden

x = {foo:1}.foo

Denn wie es steht

{} + {} + {}

"[object Object][object Object][object Object]"

;{} + {} + {}

"NaN[object Object]"

Verrückt und konsequent kann ich damit umgehen ... verrückt und inkonsistent nein danke!

James Wakefield
quelle
Eine REPL ist nicht die Sprache, sondern eine REPL. Es gibt unter anderem Zeichenfolgen an die Sprache weiter . Hier sind einige Dinge, die Chrome REPL in der Sprache selbst nicht tut . Sie sind ziemlich nützlich, deshalb bin ich wirklich froh, dass sie sich nicht nur an die einfache Sprache gehalten haben.
Gman
@gman A REPL Liest eine Zeichenfolge, wertet sie aus, druckt die Ergebnisse und bereitet dann das Lesen des nächsten dynamischen Codes vor. Nichts auf der verlinkten Seite war ungültiges JavaScript. Die Variable "$ _" für den Konsolenkontext ist eindeutig eine Annehmlichkeit, die nur in einer REPL sinnvoll ist. Trotzdem ist "$ _" ein gültiger Variablenname, der Rest sind nur normale Funktionen und Klassen, die mit normalem JavaScript aufgerufen werden.
James Wakefield
Ich bin mir nicht sicher, worum es dir geht. Mein Punkt ist, dass die Sprache eine Sache ist, die Umgebung, in der sie läuft, eine andere. Sie haben in Ihrer Antwort ein Beispiel gegeben. In JS {foo:1}und {foo:1}//produzieren das gleiche. In Chrome JS REPL ist dies nicht der Fall. Die REPL bewertet nicht nur JS. Es geht darum, die Saiten zu verarbeiten und sich für verschiedene Dinge zu entscheiden.
Gman
var x = eval('{a:1}')In gültigem JavaScript ist x jetzt 1, nicht das intuitivere Objekt {a: 1}. Ja, das ist komisch, aber Sie können die Sprache nicht einfach ändern, weil sie seltsame Dinge tut. Alles andere als JSON-Zeichenfolgen wird als JavaScript interpretiert und ausgewertet. Das Tippen 0,vor dem Einfügen des JSON ist nicht schwierig. Alternativ würde ich mich über eine Warnung freuen, dass die Zeichenfolge der Einfachheit halber als Objekt anstelle von JavaScript interpretiert wurde.
James Wakefield