Как реализовать функцию isNaN без использования Object.is в JavaScript
Что проверяют
Знаете ли вы, что NaN единственное значение в JavaScript, которое не равно самому себе, и чем глобальный isNaN отличается от Number.isNaN. Следом почти всегда спрашивают, почему isNaN('abc') возвращает true, и какую из двух семантик вы реализовали.
Как отвечать
Сначала уточните, какое поведение нужно повторить. Их два:
- как
Number.isNaN:typeof value === 'number' && value !== value. Без приведения типов, строка,undefinedи объект даютfalse. Это стандартный полифил,Number.isNaNпоявился в ES2015; - как глобальный
isNaN: сначала приведение к числу, потом та же проверка:const n = +value; return n !== n;. ЗдесьisNaN('abc'),isNaN(undefined)иisNaN({})даютtrue, аisNaN(''),isNaN(null)иisNaN([])даютfalse, потому что пустая строка,nullи пустой массив приводятся к нулю.
Почему работает самосравнение: по стандарту IEEE 754 NaN не равен ничему, включая себя, и === это правило соблюдает.
Для второго варианта унарный плюс точнее, чем Number(value). Плюс выполняет то же приведение, что встроенная функция, поэтому на BigInt и Symbol бросает TypeError, как оригинал. А Number(10n) молча вернёт 10.
Если попросят ещё способ без Object.is, подойдёт [NaN].includes(value): includes сравнивает по алгоритму SameValueZero, где NaN равен NaN.
Где спотыкаются
Пишут вариант с typeof и утверждают, что он повторяет встроенный isNaN. На строке 'test' ваша функция вернёт false, а встроенная true. Это две разные функции, и надо назвать, какую из них вы написали.
Проверяют value === NaN или arr.indexOf(NaN). Оба варианта всегда дают «не найдено»: строгое равенство NaN не находит, в отличие от includes.
Используют isNaN для проверки пользовательского ввода. isNaN('') и isNaN(' ') возвращают false, то есть пустое поле сойдёт за число. Для валидации надёжнее отсечь пустую строку и проверить Number.isFinite(Number(str)).