2015-05-11 19 views
11

Stavo solo giocando in giro con javascript quando ho trovato le seguenti uscite della console:aggiunta su due oggetti vuoti o array vuoti in javascript

  1. [] + [] // output: ""
  2. [] + {} // output : [Object oggetto]
  3. {} + [] // output: 0
  4. {} + {} // output: NaN

Qualcuno potrebbe spiegarmi la logica dietro questi output. Sento che è un comportamento molto strano ma credo che abbia qualche logica.

Grazie in anticipo.

+2

Sigh, so che questo è stato chiesto prima, ma così non consente di ricercare '{}' e '[]' perché non sono parole. – Barmar

+1

[1:20 di questo video] (https://archive.org/details/wat_destroyallsoftware) – Andy

risposta

9

Risultati attesi

Quando si aggiungono due array, tutto funziona come previsto:

[] + []//output'' 

Conversione [] ad una primitiva primi tentativi valueOf() che restituisce la matrice stessa (this):

var arr = []; 
arr.valueOf() === arr 
true 

Come risultato non è un pr imitive, toString() viene chiamato next e restituisce la stringa vuota (che è una primitiva). Pertanto, il risultato di [] + [] è la concatenazione di due stringhe vuote.

{} + [] // output: 0 

Aggiunta una matrice e un oggetto conforme anche alle nostre aspettative:

[] + {}//output '[object Object]' 

Spiegazione: conversione di un oggetto vuoto a stringa restituisce il seguente risultato.

String({})//output: '[object Object]' 

Il risultato precedente viene così creato concatenando "" e "[object Object]".

risultati inattesi

cose strane se il primo operando di + è un oggetto vuoto letterale (risultati come visto sulla console Firefox):

{} + {}//output: NaN 

cosa sta succedendo qui? Il problema è che JavaScript interpreta il primo {} come un blocco di codice vuoto e lo ignora. Il NaN viene quindi calcolato valutando +{} (seguito dal secondo {}). Il vantaggio visualizzato qui non è l'operatore di aggiunta binaria, ma un operatore di prefisso unario che converte il suo operando in un numero, allo stesso modo di Number().Per esempio:

+"3.65" 
3.65 

Le seguenti espressioni sono tutte equivalenti:

+{} 
Number({}) 
Number({}.toString()) // {}.valueOf() isn’t primitive 
Number("[object Object]") 
NaN 

Perché la prima {} interpretato come un blocco di codice? Poiché l'input completo viene analizzato come un'istruzione e le parentesi graffe all'inizio di un'istruzione vengono interpretate come l'avvio di un blocco di codice. Quindi, è possibile sistemare le cose per forzare l'ingresso da analizzare come espressione:

({} + {})//output: '[object Object][object Object]' 

Argomenti delle funzioni o metodi sono anche sempre analizzati come espressioni:

console.log({} + {})//output: [object Object][object Object] 

Dopo le spiegazioni precedenti, si dovrebbe non essere sorpreso il seguente risultato, più:

{} + []//output: 0 

nuovo, questo viene interpretato come un blocco di codice seguito da +[]. Le seguenti espressioni sono equivalenti:

+[] 
Number([]) 
Number([].toString()) // [].valueOf() isn’t primitive 
Number("") 
0 

interessante notare che il Node.js REPL analizza il suo ingresso in modo diverso sia da Firefox o Chrome (che utilizza anche lo stesso motore V8 JavaScript come Node.js). Il seguente ingresso viene analizzato come le espressioni ed i risultati sono meno sorprendenti:

{} + {}//output: '[object Object][object Object]' 
{} + []//output '[object Object]' 

Questo ha il vantaggio di essere più come il risultato che si ottiene quando si utilizza l'ingresso come argomenti di console.log(). Ma è anche meno come utilizzare l'input come istruzioni nei programmi.

Referenze

What is {} + {} in JavaScript?

Problemi correlati