2013-02-08 2 views
48

Недавно я нашел одну странную строку в источниках JQuery (последняя версия 1.9.1, Шипение пакет, строка 129 funescape функция):Странный код в источниках 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); 
}; 

В чем причина, чтобы сделать high !== high сравнение? Очевидно, что return escaped никогда не будет выполнен. Или мне что-то не хватает?

Ссылка:https://github.com/jquery/sizzle/blob/master/sizzle.js#L129

+1

, может быть ошибка? которая является функцией ожидаемой подписи? Я также вижу неиспользуемый аргумент '' _'', ... – redShadow

+3

@redShadow Ну, '_' понятен, поскольку по какой-либо причине (возможно, для сохранения совместимости) авторам необходимо получить только второй аргумент, вместо этого используйте 'arguments [1]'. – VisioN

+5

Я думаю, что, как говорится в комментарии, 'NaN! == NaN' будет ** всегда ** возвращать' true' – Alexander

ответ

57

На самом деле написано в комментарии прямо над:

// NaN означает не элемент кода

Так оно является обязательным для выполнения этого сравнение сначала для обработки дела NaN, как в JavaScript:

NaN === NaNfalse.

Как указано James Wiseman, также важно знать, почему разработчик использовал high !== high вместо isNaN(high), который был бы яснее.

Это, конечно, основано на характеристиках. Это test показывает, что a !== a является в двадцать раз быстрее, чем isNaN(a).

zzzzBov также указывает, что isNaN() может быть перезаписано, используя !== также более портативно.

Более подробную информацию от Benjamin Gruenbaum:

Также стоит отметить, что NaN не равно ни к чему другому, как а, а также оно не равно ни к чему-то в unstrict смысле

И от Jan Dvorak:

внимание также {valueOf:function(){return{}}} делает равный себя

+2

+1 Я думал то же самое, но я новый программист: D –

+3

Стоит также отметить, что NaN тоже не соответствует чему-либо еще, а также не соответствует чему-либо еще в нестрогом смысле. –

+1

Также обратите внимание на '{valueOf: function() {return {}}}' _does_ equal yourself –

13

Условие high !== high возвращает истину, когда высока NaN .Я интересно, почему ребята Jquery не использовали много четкого isNaN(high) функции вместо этого, но это было, вероятно, из-за соображений производительности, как koopajah указал.

NaN (N ot- a - N умбра) означает результат, который не может быть представлено в виде Number. Это неопределенное число.


Почему NaN === NaN возвращает ложь?

Рассмотрим

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

Вы знаете, что 0/0 отличается Math.asin(2), так почему whould NaN быть равна NaN?

+1

Еще одна потенциальная причина, по которой 'NaN === NaN' возвращает false, - это' NaN' имеет более одного битового шаблона. –

6

Я поддерживаю некоторые комментарии здесь, но думаю, что это достойная информация.

Некоторых замечаний по первоначальному вопросу предположил, что этот метод проверки NaN на самом деле гораздо быстрее, чем isNaN()

Когда в сочетании со следующей альтернативой parseIntparseFloat у нас есть очень быстрый способ преобразования к число и проверку его числового состояния.

Is Subtracting Zero some sort of JavaScript performance trick?

Таким образом, вместо

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

Мы можем

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

'val - 0' является * not * подходящей заменой' parseFloat (val) '. Например, результаты очень разные, если 'val = '0xFF''. – zzzzBov

+0

'Number (val)' равнозначно 'val - 0' или более просто' + val'. – zzzzBov