Perché {} + {} non è più NaN nella console di Chrome?


144

Ho notato oggi che Chrome 49 non viene più emesso NaNquando si digita {}+{}nella console. Invece genera la stringa [object Object][object Object].

Perchè è questo? La lingua è cambiata?


13
sembra che Chrome ora consideri questa operazione come un concat stringa piuttosto che un'aggiunta. PERCHÉ questo è, non lo so, motivo per cui questo è un commento non una risposta :) prova var e = {}; e.toString()e vedrai cosa intendo
user428517

19
"La lingua è cambiata?" No.
Felix Kling

6
@FelixKling La lingua cambierà? ...no. : c
gatto,

18
Forse WATMAN aveva qualcosa a che fare con questo?
rickster

1
@Rickster è così che l'ho trovato. Lo stavo ricreando per una presentazione.
Filip Haglund,

Risposte:


152

Gli sviluppatori Chrome ora avvolgono automaticamente tutto ciò che inizia {e finisce con }una coppia implicita di parentesi ( vedi codice ), per forzare la sua valutazione come espressione. In questo modo, {}crea un oggetto vuoto ora. Puoi vedere questo se torni indietro nella cronologia ( ), la riga precedente sarà contenuta in (…).

Perché? Non lo so, ma immagino che riduca la confusione per i neofiti che non conoscono la cosa letterale block-vs-object, ed è anche più utile se vuoi solo valutare un'espressione.

E in effetti questo è il ragionamento, come discusso nel bug 499864 . Pura convenienza. E poiché anche il nodo REPL lo aveva ( vedi codice ).


182
Stupido Chrome, {a:1}),({b:2}dovrebbe generare un errore, non produrre un oggetto.
Oriol

29
Questo è ciò che accade quando analizzi strutture nidificate arbitrariamente profonde con regex stackoverflow.com/questions/1732348/…
Filip Haglund

4
Non ho idea del perché, ma in qualche modo quando vedo i miei messaggi lì mi sento "famoso" anche se quella pagina è pubblica come questa: D Weird StackOverflow problem. Ecco la mia risposta più vecchia sul problema stackoverflow.com/questions/17268468/…
Benjamin Gruenbaum,

3
Non mi piace l'implementazione attuale e ho intenzione di risolverlo. bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak

1
@Zirak Buona fortuna a riparare quella spazzatura, IMO dovrebbe essere ritirato al più presto. Ma se vuoi migliorarlo, considera l'aggiunta di una nuova riga prima dell'inserimento )nel caso in cui sia in un commento, ad esempio {a:3} // :-}potrebbe comunque produrre un oggetto.
Oriol

44

Se premi la freccia su dopo aver verificato questo, noterai che invece di {} + {}esso viene visualizzato ({} + {}), il che si traduce in "[object Object][object Object]".

In confronto, in Firefox, {} + {}viene ancora visualizzato NaN, ma se lo fai ({} + {})viene visualizzato anche "[object Object][object Object]".

Quindi, sembra che Chrome stia aggiungendo automaticamente la parentesi circostante quando vede questa operazione.


22
questa risposta è corretta. ma wow, amico, non sono sicuro che mi piaccia quel Chrome. cattivo google.
user428517

1
@sgroves Sarei interessato a vedere se questo è lo stesso in Canarie, e se è stato fatto apposta o in realtà è un bug.
J. Titus,

8
{} + {}quando non "sanificato" ({} + {})viene trattato come + {}perché {}viene analizzato come un blocco vuoto.
Gregory Nisbet,

7
Perché dovrebbe restituire NaN in primo luogo?
0x499602D2

25
@ 0x499602D2: Perché, a meno che non si eseguano le parentesi (o altrimenti si induca il parser a aspettarsi un'espressione piuttosto che un'istruzione), l'iniziale {}è solo un blocco di codice vuoto e viene ignorato, lasciandoci con +{}, che è un oggetto unario +e vuoto initializer. +costringerà il suo argomento al numero, che implica la conversione dell'oggetto in una primitiva (che finirà per essere un toStringin questo caso, risultante in "[object Object]"), e quindi otteniamo +"[object Object]"che è NaNperché "[object Object]"non può essere convertito in un numero valido.
TJ Crowder,

4

A partire da Chrome 54 per quanto riguarda la console:

📎- "Ho convertito quel blocco in un oggetto per te" -Clippy Sfortunatamente, ho aggiunto io stesso la citazione di Clippy. La console non fornisce informazioni su ciò che ha fatto per te.

Le nuove regole sono incredibilmente semplici e ci risparmiano il problema di digitare faticosamente questi 2 caratteri difficili o=o0, prima di incollare Object Literals nella console:

  • Se si dispone di codice che inizia con: spazio bianco facoltativo, (nessun commento consentito) seguito da a { ;
  • e quel codice potrebbe essere interpretato come un oggetto;
  • e quell'oggetto non è seguito da nessun altro codice, a meno che:
  • il codice dopo il primo oggetto è un operatore binario,
  • quindi possono esserci tutte le operazioni che desideri, inclusi i raggruppamenti
  • purché l'operatore finale abbia un Oggetto letterale nella posizione di destra;
  • e quell'oggetto finale non è stato raggruppato in parentesi
  • e quel codice non termina con un punto e virgola
  • e non ci sono commenti che seguono il codice (i commenti interni sono consentiti purché non si trovino nella posizione iniziale o finale)
  • quindi e solo allora il tuo JavaScript (che può essere o meno effettivamente un codice valido) verrà reintrodotto come un oggetto valido. Non sarai informato che il tuo codice è stato reinterpretato.

{wat:1}),({wat:2} È finalmente di nuovo un errore.

{let i=0;var increment=_=>i++} è correttamente consentito, infine, che è un bel modo di fare chiusure.

Tuttavia, quanto segue è erroneamente un oggetto, questo è altrettanto comodo come indicato da @Bergi, interpreta JS errato per aiutarti! La specifica dice che è un blocco con un'istruzione etichettata "pippo" con un 1 letterale che non è assegnato a nulla.

{foo:1}

Quanto sopra dovrebbe essere lo stesso di

if(1) {
    foo: 1
}

Quello che segue è trattato correttamente come un blocco ... perché ha un commento davanti!

//magic comment
{foo:1}

Quindi è questo:

{foo:1}
//also magic

Questo è un oggetto:

{foo:
//not so magic comment
1}

Questo è un errore

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

Quindi è questo:

{foo:1}.foo

Questo va bene:

1..wat

undefined

così è questo:

['foo'][0]

Il prossimo viene correttamente interpretato come un oggetto inciso nella posizione dell'espressione con un 0,che è generalmente il modo in cui assicuriamo inequivocabilmente di avere un'espressione invece di un'istruzione.

0,{foo:1}.foo

Non capisco perché racchiudano il valore in parentesi. JS ha alcune decisioni ridicole sul design, ma cercare di farlo funzionare meglio in questa situazione non è davvero un'opzione, la console deve eseguire correttamente JS e dobbiamo essere sicuri che Chrome non stia solo indovinando che pensa che noi intendevo davvero fare qualcos'altro.

Se non ti piacciono gli operatori virgola, puoi usare il compito

x = {foo:1}.foo

Perché così com'è

{} + {} + {}

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

;{} + {} + {}

"NaN[object Object]"

Pazzo e coerente che posso affrontare ... pazzo e incoerente no grazie!


un REPL non è la lingua è un REPL. Passa le stringhe alla lingua tra le altre cose . Ecco alcune cose che il REPL di Chrome non utilizza la lingua stessa . Sono piuttosto utili, quindi sono davvero contento che non si siano limitati al solo linguaggio semplice.
Gman,

@gman A REPL Legge una stringa, la valuta, stampa i risultati e quindi si prepara a leggere il prossimo pezzo di codice dinamico. Nulla nella pagina collegata era JavaScript non valido. La variabile "$ _" nell'ambito del contesto della console è chiaramente una comodità che ha senso solo in un REPL. Tuttavia, "$ _" è un nome di variabile valido, il resto sono solo normali funzioni e classi invocate con JavaScript normale.
James Wakefield,

Non sono sicuro di quale sia il tuo punto. Il mio punto è che la lingua è una cosa, l'ambiente in cui corre è un'altra. Hai dato un esempio nella tua risposta. In JS{foo:1} e {foo:1}//produci la stessa cosa. Nel Chrome JS REPL non lo fanno. Il REPL sta facendo molto di più che valutare JS. Sta elaborando le stringhe e decidendo di cose diverse.
Gman

var x = eval('{a:1}')In JavaScript valido x ora è 1, non l'oggetto più intuitivo {a: 1}. Sì, è strano, ma non puoi semplicemente cambiare la lingua perché fa cose strane. Tutto tranne le stringhe JSON vengono interpretate come JavaScript e valutate. Digitare 0,prima di incollare il JSON non è difficile, in alternativa sarei felice di avvertire che la stringa è stata interpretata come un oggetto anziché JavaScript per comodità.
James Wakefield,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.