Invece di ripetere semplicemente il risultato che hai dimostrato nella domanda, proverò a fornire una descrizione di perché il risultato è.
Spiegazione
Prendendo solo il primo esempio (perché il resto lo farà qualcosa di simile), siamo in grado di seguire le specifiche per vedere cosa succede.
Da 11.4.6 Unary + Operator, possiamo vedere che una conversione ToNumber
ha luogo.
Return ToNumber (GetValue (expr)).
Da 9.3 ToNumber vediamo che se dato un oggetto (come il tuo Array), una conversione ToPrimitive
avviene seguito da un altro tentativo di ToNumber
.
oggetto
seguire le istruzioni seguenti:
- Let primValue essere ToPrimitive (argomento di input, numero suggerimento).
- Return ToNumber (primValue).
Da 9.1 To Primitive, se ToPrimitive
Ottiene un oggetto, possiamo vedere che la sua [[DefaultValue]]
è inverosimile:
oggetto
Ritorna un valore predefinito per l'oggetto. Il valore predefinito di un oggetto viene recuperato chiamando il metodo interno [[DefaultValue]] dell'oggetto, passando il suggerimento opzionale PreferredType. Il comportamento del metodo interno [[DefaultValue]] interno è definito da questa specifica per tutti gli oggetti nativi ECMAScript in 8.12.8.
Da 8.12.8 [[DefaultValue]] (hint), quello che alla fine sarà accadere che toString()
saranno chiamati Array e restituito. Questa stringa viene inviata al ricorsivo ToNumber
come descritto sopra.
Quindi cosa succede quando la conversione ToNumber
viene eseguita su una stringa? Bene è descritto in 9.3.1 ToNumber Applied to the String Type, ed è un po 'lungo. Più semplice è quello di fare solo la conversione direttamente, e vedere cosa succede:
Number(""); // result is 0 on an empty string
Number(" "); // result is 0 on a string with only whitespace
Number("123"); // result is 123 on a numeric string
Number(" 123 ");// result is 123 on a numeric string with leading & trailing spaces
Number("abc"); // result is NaN (not a number) on non-numeric strings
Quindi la domanda è: cosa fare stringa torniamo dal nostro array. Di nuovo, questo è facile da provare semplicemente.
[].toString(); // result is "" (empty string)
Poiché il risultato è una stringa vuota, e una conversione ToNumber
di una stringa vuota è 0
come mostrato sopra, ciò significherebbe stiamo confrontando 0 === 0
.
Sarebbe lo stesso come se abbiamo fatto:
Number([].toString()) === 0; // true
O per tirarlo fuori un po 'di più:
var x = [];
x = x.toString(); // ""
x = Number(x); // 0
x === 0; // true
Più toString
risultati.
per mostrare più toString
conversioni di Array, considerare quanto segue:
[1].toString(); // "1"
[1,2,3].toString(); // "1,2,3"
["a",1,"b",2].toString(); // "a,1,b,2"
Quindi, per fare una conversione ToNumber
sugli array di cui sopra, la prima ci darebbe un numero, e gli ultimi due si tradurrebbe in NaN
.
Number([1]); // 1
Number([1,2,3]); // NaN
Number(["a",1,"b",2]); // NaN
Alcuni prova
Per fornire ulteriore prova che questa conversione toString()
avviene prima della conversione ToNumber
, possiamo effettivamente modificare Array.prototype.toString
per fornire un risultato diverso, e qualsiasi ToNumber
conversioni useremo che risultato modificato.
Array.prototype.toString = function() {
var n = 0;
for(var i = 0; i < this.length; i++) {
n += this[i];
}
return n;
};
Qui ho sostituito il toString
su Array.prototype
con una funzione che somma l'Array. Ovviamente non vuoi farlo, ma possiamo mostrare come otterremo un risultato diverso.
Number([1,2,3]); // 6
+[1,2,3]; // 6
Così ora si può vedere che la conversione del nostro Array ToNumber
che in precedenza hanno portato a NaN
è ora traduce nella somma degli elementi della matrice.
Penso che avrei capovolto la scrivania se mi imbattessi in un codice del genere. –
la risposta è: '+ [NaN] == !!!! 0 && + [{}] + ~~ [[]] - []' – jAndy
Se ho visto che in qualsiasi codebase avrei chiesto allo sviluppatore originale di riscrivere esso. È una pessima pratica !!! –