О NaN больше всего известно то, что он не равен самому себе.
NaN === NaN // false
И что операции, невозможные арифметически, вернут NaN.
'BlaBlaBla'/0 // NaN
Но у NaN есть одно мало известное(?), и, как мне кажется, весьма полезное применение.
TL;DR Все дело в Date
В двух словах:
new Date(NaN) // Invalid Date
Чем полезно? Invalid Date все равно Date. И все операции с Date все ещё на месте.
Любые операции с Date, кроме прямой установки timestamp вернут NaN, оставив Date как Invalid Date.
const x = new Date(NaN) // Invalid Date
x.setTime(12345) // 12345
x.toString() // "Thu Jan 01 1970 00:00:12 GMT+0000 (+00)"
При этом, проверка на валидность даты становится проще некуда
const x = new Date(NaN) // Invalid Date
isNaN(x) // true
x.setTime(0)
isNaN(x) // false
Заметьте, преобразование в timestamp здесь не требуется, valueOf() делает это под капотом.
Все операции с Date — мутабельные. Тем не менее, клонирование через конструктор прекрасно работает и с Invalid Date.
const x = new Date(NaN) // Invalid Date
const y = new Date(x) // Invalid Date
Сравнение двух дат напрямую в Date не реализовано и сравнивать даты можно только через timestamp. NaN гарантирует что Invalid Date точно не будет равно никакой другой дате. Думаю, это весьма полезное свойство.
const x = new Date(NaN) // Invalid Date
const y = new Date(NaN) // Invalid Date
x.getTime() === y.getTime() // false
К моему сожалению, конструктор Date ведёт себя несколько странно по отношению к входному параметру.
new Date(null) // Thu Jan 01 1970 00:00:00 GMT+0000 (+00)
Было бы намного логичнее конструировать Invalid Date, ведь null — это не совсем ноль. Оставим это на совести Javascript-а.
Однако, если насильственно передать в конструктор undefined, то результат выглядит ожидаемым. Так что будьте осторожны.
new Date(undefined) // Invalid Date
Статья получилась больше о Date чем о NaN, но, в целом, именно об этой связке я хотел рассказать.
Автор: ua9msn