2013-02-08 14 views
48

Niedawno znalazłem jedną linię dziwne w źródłach jQuery (ostatnia wersja 1.9.1, pakiet Trzask, linia 129 funescape funkcji):Dziwny kod w źródłach 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); 
}; 

Jaki jest powód, aby high !== high porównania? To oczywiście wygląda na to, że return escaped nigdy nie zostanie wykonane. Czy może czegoś nie przeoczyłem?

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

+1

Może bug? która funkcja oczekuje podpisu? Widzę także nieużywany argument '' _'', – redShadow

+3

@redShadow Cóż, '_' jest zrozumiały, ponieważ z jakiegoś powodu (być może w celu zachowania zgodności), autorzy muszą uzyskać tylko drugi argument, oprócz tego zamiast tego użyj 'arguments [1]'. – VisioN

+5

Myślę, że jest tak jak w komentarzu: 'NaN! == NaN' będzie ** zawsze ** zwraca' true' – Alexander

Odpowiedz

57

W rzeczywistości to jest napisane w komentarzu tuż powyżej:

// NaN oznacza zakaz kodowy

Więc jest to obowiązkowe, aby wykonać porównanie najpierw do obsługi sprawy NaN jak w JavaScript:

NaN === NaN zwraca false.

Jak podkreślił James Wiseman, ważne jest również, aby dowiedzieć się, dlaczego programista użył high !== high zamiast isNaN(high), które byłyby jaśniejsze.

Jest to z pewnością oparte na wydajności. Ten test pokazuje, że a !== a jest dwudziestokrotnie szybszy od niż isNaN(a).

oznacza również, że można nadpisać isNaN(), przy użyciu !== jest również bardziej przenośny.

Więcej informacji od Benjamin Gruenbaum:

Warto również zauważyć, że NaN nie równa się z niczym innym jak dobrze, a także nie jest równa cokolwiek innego w unstrict sensie

I od Jan Dvorak:

Należy również pamiętać {valueOf:function(){return{}}} ma równego sobie

+2

+1 Myślałem o tym samym, ale jestem nowym programistą: D –

+3

Warto również zauważyć, że NaN nie równa się z niczym innym, jak również, a także nie jest równe z niczym innym w niestratnym sensie. –

+1

Należy również zwrócić uwagę na '{valueOf: function() {return {}}}' _does_ equal itself –

13

Warunkiem high !== high zwraca true, gdy wysoki jest NaN .I zastanawiać dlaczego faceci jQuery nie użył dużo jasnego isNaN(high) funkcję zamiast, ale to było prawdopodobnie ze względów wydajności jak koopajah zauważył.

NaN (N OT a - N umbra) znaczy taki, który nie może być przedstawiony jako Number. Jest to liczba nieokreślona.


Dlaczego NaN === NaN zwraca wartość false?

Rozważmy

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

Wiesz, że 0/0 jest inny niż Math.asin(2), więc dlaczego whould NaN być równa NaN?

+1

Innym potencjalnym powodem, dla którego 'NaN === NaN' zwraca false jest' NaN' ma więcej niż jeden wzorzec bitowy. –

6

Jestem piggy-backing na niektóre z komentarzy tutaj, ale myślę, że ta godna informacja.

kilka uwag na temat pierwotnego pytania sugerują, że ta metoda sprawdzania NaN jest rzeczywiście znacznie szybciej niż isNaN()

Gdy podjęte w związku z następującą alternatywę parseIntparseFloat mamy bardzo szybki sposób konwersji na numer i sprawdzenie jego stanu numerycznego.

Is Subtracting Zero some sort of JavaScript performance trick?

Więc zamiast

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

Możemy mieć

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

'val - 0' is * not * nie jest odpowiednim zamiennikiem' parseFloat (val) '. Na przykład wyniki są bardzo różne, jeśli 'val = '0xFF''. – zzzzBov

+0

'Number (val)' jest równoważne "val - 0", lub bardziej prosto '+ val'. – zzzzBov

Powiązane problemy