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?
Sigh, so che questo è stato chiesto prima, ma così non consente di ricercare '{}' e '[]' perché non sono parole. – Barmar
[1:20 di questo video] (https://archive.org/details/wat_destroyallsoftware) – Andy