Почему parseInt в JavaScript может возвращать NaN и как влияет второй аргумент
Что проверяют
Понимаете ли вы, что parseInt разбирает начало строки, а не проверяет её целиком, и зачем нужен второй аргумент. Заодно это проверка аккуратности: функция старая, поведение у неё неочевидное, и знание деталей отличает практика от прочитавшего справку по диагонали.
Как отвечать
Алгоритм короткий: аргумент приводится к строке, пропускаются пробелы, читается знак, определяется основание, дальше берётся максимально длинная подходящая последовательность цифр. Если не удалось прочитать ни одной цифры, получается NaN. Отсюда и parseInt("abc"), и пустая строка, и parseInt(null), где строкой оказывается слово, а не число.
Второй аргумент это основание системы счисления, от 2 до 36. Если его не передать, строка с префиксом 0x читается как шестнадцатеричная, всё остальное как десятичная. Указывать основание явно стоит всегда: это дешевле, чем однажды разбираться, почему идентификатор из формы прочитался не так.
parseInt("0x1f"); // 31
parseInt("1f", 16); // 31
parseInt("12", 2); // 1, вторая цифра для двоичной уже не годится
parseInt("12px"); // 12, а Number("12px") даст NaN
parseInt(0.0000005); // 5, потому что число сначала стало строкой вида 5e-7Закончить стоит выбором инструмента: parseInt берут, когда у числа заведомо есть хвост, а для строгой проверки ввода лучше Number с последующей проверкой результата.
Где спотыкаются
Не передают основание, объясняя это тем, что там и так десятка. Для строки с шестнадцатеричным префиксом это не так, и на данных из внешнего источника расхождение находится далеко не сразу.
Используют parseInt как валидацию. Он разбирает начало строки и молча отбрасывает остальное, поэтому запись с запятой в дробной части превратится в целое без всякой ошибки.
Передают parseInt прямо в map и удивляются результату: вторым аргументом туда прилетает индекс, то есть основание. Рядом живёт вторая классика: сравнение с NaN через равенство всегда ложно, проверять нужно через Number.isNaN.