2013-02-08 18 views
48

Recentemente ho trovato una riga strano nelle fonti jQuery (ultima versione 1.9.1, pacchetto Sizzle, linea di funzione 129 funescape):Codice strano in sorgenti jQuery: var! == var? x: y;

funescape = function(_, escaped) { 
    var high = "0x" + escaped - 0x10000; 
    // NaN means non-codepoint 
    return high !== high ?   // <--- LINE 129 
     escaped : 
     // BMP codepoint 
     high < 0 ? 
      String.fromCharCode(high + 0x10000) : 
      // Supplemental Plane codepoint (surrogate pair) 
      String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00); 
}; 

Qual è la ragione per fare high !== high confronto? Ovviamente sembra che return escaped non venga mai eseguito. O mi manca qualcosa?

Riferimento:https://github.com/jquery/sizzle/blob/master/sizzle.js#L129

+1

forse un bug? qual è la firma prevista della funzione? Vedo anche un argomento '' _'' inutilizzato, ... – redShadow

+3

@redShadow Beh, '_' è comprensibile, dal momento che per qualche ragione (possibilmente per preservare la compatibilità) gli autori devono ottenere solo il secondo argomento, oltre a usa invece 'arguments [1]'. – VisioN

+5

Penso che sia come dice il commento, 'NaN! == NaN' sarà ** sempre ** restituirà' true' – Alexander

risposta

57

Infatti è scritto nel commento proprio sopra:

// NaN significa non codepoint

Quindi è obbligatorio per eseguire questa confronto prima per gestire il caso NaN come in JavaScript:

NaN === NaN restituisce false.

Come sottolineato da James Wiseman è anche importante sapere perché lo sviluppatore ha utilizzato high !== high anziché isNaN(high) che sarebbe stato più chiaro.

Si basa sicuramente sulle prestazioni. Questo test mostra che a !== a è venti volte più veloce rispetto a isNaN(a).

zzzzBov indica inoltre che isNaN() potrebbe essere sovrascritto, utilizzando !== è anche più portabile.

Informazioni da Benjamin Gruenbaum:

E 'anche interessante notare che NaN non è uguale a qualsiasi altra cosa, come bene, e anche che non è uguale a qualsiasi altra cosa in senso unstrict

E da Jan Dvorak:

noti inoltre {valueOf:function(){return{}}} è uguale per sé

+2

+1 Ho pensato lo stesso ma sono un nuovo programmatore: D –

+3

Vale anche la pena notare che NaN non è uguale a nient'altro, e inoltre non è uguale a nient'altro in senso stretto. –

+1

Nota anche '{valueOf: function() {return {}}}' _does_ uguale a se stesso –

13

La condizione high !== high restituisce vero, quando l'alta viene NaN .I chiedono perché i ragazzi jQuery non utilizzate la funzione molto chiara isNaN(high) invece, ma che era probabilmente a causa di motivi di prestazioni come koopajah sottolineato.

NaN (N ot- a - N terra d'ombra) indica un risultato che non può essere rappresentato come un Number. È un numero indeterminato.


Perché NaN === NaN restituisce false?

consideri

0/0   = NaN 
Math.asin(2) = NaN 

Voi sapete che 0/0 è diverso Math.asin(2), quindi perché whould NaN essere uguale a NaN?

+1

Un'altra potenziale ragione per cui 'NaN === NaN' restituisce false è' NaN' ha più di un modello di bit. –

6

Sto piggy-backing su alcuni dei commenti qui, ma penso che questa degna informazione.

Alcune osservazioni sulla domanda iniziale hanno suggerito che questo metodo di verifica di Nan è in realtà molto più veloce di isNaN()

se assunto in combinazione con la seguente alternativa a parseIntparseFloat abbiamo un modo molto veloce di conversione in un numero e controllarne lo stato numerico.

Is Subtracting Zero some sort of JavaScript performance trick?

Così, invece di

function Translated(val) { 
    var x = parseFloat(val); 
    if (!isNaN(x)) { 
     alert("Not a number"); 
    } 
} 

Possiamo avere

function WTF(val) { 
    var x = val - 0; 
    if (x !== x) { 
     alert("Not a number"); 
    } 
} 
+0

'val - 0' è * non * un sostituto adatto per' parseFloat (val) '. Ad esempio, i risultati sono molto diversi se 'val = '0xFF''. – zzzzBov

+0

'Number (val)' è equivalente a 'val - 0', o più semplicemente' + val'. – zzzzBov