Эпичный сборник подводных камней с числами в JavaScript ?
У JS потрясающие числа. Каждое из которых может быть:
- целым,
- дробным,
- шестнадцатеричным,
- экспонентой,
- +Infinity,
- -Infinity,
- и …NaN (да, Not a Number. Не число — это число! Притом, NaN не равен NaN… что логично и иронично).
- …или число вообще может быть сравнимо-несравнимым объектом:
var x = 6;
var y = new Number(6);
x == y; // -> true; ну да, 6 равно 6.
typeof x; // -> Number
typeof y; // -> Object
z = new Number(6);
z == y // -> false; Number(6) не равен Number(6).
…потому, что объекты в JS сравнить нельзя. Зато в сравнении с примитивами они преобразовываются в примитив. Непонятно, зачем есть разновидность объекта Number, но возможность — безусловно — интересная.
Бесконечность аналогично доставляет:
var x = Infinity;
var y = -Infinity;
x + 5; // -> Infinity; логично
y - 5; // -> -Infinity; тож логично
x+y; // делаем ставки…
…Нет, Infinity + (-Infinity)
это не 0.
…Это NaN
!
То есть, если на сервер прилетает ответ от клиента, надо:
- Убедиться, что это Number, (if typeof x !== 'undefined' && typeof x === 'Number');
- Убедиться, что Number в пределах разумного. isFinite();
- Убедиться, что Number не NaN! isNaN(); (или см. ниже в примере);
- Убедиться, что Number нужного формата (например, дробное содержит точку x.toString().indexOf(".") == -1).
Сам по себе NaN тоже доставляет, т.к. такое число не равно самому себе:
var x = 5 * 'текст'; // -> NaN; ну да, тяжело умножить.
x != x; // -> true
Можно использовать для проверки на NaN, если забыли про isNaN();.
…да и дроби отдельный лулз:
var x = .1;
var y = .2;
.3 == x+y; // false; 0.1+0.2 не равно 0.3!
// А вот почему:
x+y; // -> 0.30000000000000004
…Вот что происходит, когда все без разбору числа принудительно 64-битные. Где-то в памяти должно быть 6, но на них не хватило бит.
И даже null по-своему троллит; чем взрывает мозги начисто:
null > 0; // false;
null == 0; // false;
null >= 0; // true!
…т.е. null не больше нуля и не равно нулю. Но больше или равно нулю.
Кажется, это всё :)