Per quanto riguarda la linea:
if (arr == false) console.log("It's false!");
Forse questi aiuteranno:
console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true
Quello che credo stia accadendo è che il booleano falsesia costretto a 0confrontarsi con un oggetto (il lato sinistro). L'oggetto è costretto a una stringa (la stringa vuota). Quindi, anche la stringa vuota viene forzata in un numero, ovvero zero. E così il confronto finale è 0== 0, che è true.
Modifica: vedere questa sezione delle specifiche per i dettagli su come funziona esattamente.
Ecco cosa sta succedendo, a partire dalla regola # 1:
1. Se Tipo (x) è diverso da Tipo (y), andare al passaggio 14.
La prossima regola applicabile è # 19:
19. Se Tipo (y) è Booleano, restituisce il risultato del confronto x == ToNumber (y).
Il risultato di ToNumber(false)è 0, quindi ora abbiamo:
[] == 0
Ancora una volta, la regola n. 1 ci dice di saltare al passaggio n. 14, ma il passaggio successivo che si applica effettivamente è il n. 21:
21. Se Tipo (x) è Oggetto e Tipo (y) è Stringa o Numero, restituisce il risultato del confronto ToPrimitive (x) == y.
Il risultato di ToPrimitive([])è la stringa vuota, quindi ora abbiamo:
"" == 0
Ancora una volta, la regola n. 1 ci dice di saltare al passaggio n. 14, ma il passaggio successivo che si applica effettivamente è il n. 17:
17. Se Tipo (x) è Stringa e Tipo (y) è Numero, restituisce il risultato del confronto ToNumber (x) == y.
Il risultato di ToNumber("")è 0, che ci lascia con:
0 == 0
Ora, entrambi i valori hanno lo stesso tipo, quindi i passaggi continuano dal # 1 al # 7, che dice:
7. Se x ha lo stesso valore numerico di y, restituisce true.
Quindi, torniamo true.
In breve:
ToNumber(ToPrimitive([])) == ToNumber(false)