DanLevy.net

Тест: Можно ли доверять JavaScript?

Различаете parseInt и parseFloat?

parseInt(" 123456.00")

parseInt игнорирует пробелы и парсит начальную последовательность цифр как целое число. Здесь он останавливается на десятичной точке, поэтому возвращается только 123456.

parseInt("123,456.00")

Как правило, parseInt прекращает разбор, когда встречает нечисловой символ. Здесь он останавливается на запятой, поэтому возвращается только 123.

0.1 + 0.2 === 0.3

Из‑за ошибок точности плавающих точек, 0.1 + 0.2 не равно точно 0.3. Из‑за того, как числа с плавающей запятой хранятся в памяти, результат равен 0.30000000000000004. Виноват стандарт IEEE 754 для работы с плавающей арифметикой — он не может точно представить некоторые числа. Это распространённая проблема во всех языках программирования. В конце концов вы столкнётесь с бесконечно повторяющейся десятичной дробью, и независимо от языка компьютер просто прекращает бесконечно генерировать цифры.

Некоторые языки, такие как Python и Java, имеют Decimal или BigDecimal для решения этой задачи, но в JavaScript их нет. Можно использовать библиотеки вроде big.js или decimal.js.

(Примечание: Некоторые языки предназначены для работы с дробями, мнимыми числами и т.п. на более высоком логическом уровне, сохраняя буквальные выражения. Но они всё равно сталкиваются с теми же проблемами точности плавающих точек на уровне аппаратуры.)

Number.MAX_VALUE * 2

Поскольку Number.MAX_VALUE — самое большое представимое обычное число в JavaScript, превышение его предела быстро приводит к переполнению — в результате получаются бессмысленные значения. Умножив его на 2, получаем Infinity.

Знаете, JavaScript иногда таков.

Что это может сделать?

5..toFixed(2)

.toFixed(2) возвращает строковое представление 5 с двумя знаками после запятой, поэтому результат — "5.00".

Двойная точка (5..toFixed(2)) — это «трюк», позволяющий обратиться к объектной модели числовых литералов.

parseInt("42") === parseFloat("42")

В JavaScript оба parseInt и parseFloat интерпретируют строку “42” как число 42. Поэтому сравнение parseInt("42") === parseFloat("42") дает true. parseInt прекращает разбор при первом недвоичным символе, тогда как parseFloat продолжает, пока не встретит символ, не являющийся частью числа с плавающей точкой. Однако в строке “42” нет десятичной точки или других недопустимых символов, поэтому обе функции возвращают одинаковое значение.

BigInt("42") === parseInt("42")

BigInt — это другой тип, отличающийся от number, поэтому parseInt("42") (обычное число) не строго равно BigInt("42"). Чтобы сравнить, нужно привести оба к одному типу: BigInt(parseInt("42")) === BigInt("42").

Что получится?

parseInt("0x2A") === parseInt("2a", 16)

Любая входная строка, начинающаяся с 0x, автоматически рассматривается как шестнадцатеричная (основание 16). Поэтому это эквивалентно передаче radix 16. Таким образом, parseInt("0x2A") то же самое, что parseInt("2a", 16). (Регистронезависимо.)

В чём тут дело?

parseInt('0xFF', 16)

parseInt с шестнадцатеричным основанием (16) преобразует "FF" в 255 в десятичной системе. Вы могли видеть это в CSS‑цветах RGB/Hex.

[24, 'One', 42].map(parseInt)

Второй аргумент parseInt (radix) совпадает с аргументом index, который передаёт метод массива. Это приводит к неожиданным результатам, так как parseInt("One", 1) возвращает NaN из‑за недопустимого ввода.

Первый элемент, 24, парсится как 24 в базе 0 (авто‑детект), поэтому остаётся 24. Второй элемент, 'One', парсится как NaN в базе 1. Третий элемент, 42, парсится в базе 2. В базе 2 строка '42' даёт NaN, так что результат [24, NaN, NaN].

Это распространённая ловушка при использовании parseInt с map. Если нужно превратить массив строк в числа, единственный безопасный «встроенный» способ — .map(Number) или явно указать колбэк, например .map(x => parseInt(x, 10)).

[24, 'Twenty1', 0o42].map(Number)

Number преобразует значения в числовой тип строже, чем parseInt. Здесь 'Twenty1' превращается в NaN, а 0o42 распознаётся как восьмеричный литерал и преобразуется в 34.

Каков будет результат этого кода?

console.log(parseInt(null), Number(null))

parseInt приводит ввод к строке, поэтому null становится "null". Поскольку у "null" нет валидных десятичных символов (обычных цифр), он вернёт NaN.

Number(null) возвращает 0. потому что JS любит держать вас в напряжении. Почему? Ну, могу углубиться, если есть интерес.

Каков будет результат этого заклинания?

parseInt(null, 36)

Поскольку parseInt всегда приводит ввод к строке, null превращается в строку "null".

В системе счисления base 36 (шестнадцатерично‑тридцатишестиричная, если вам интересно), строка "null" представляет 1112745.

Последовательные значения nulk, null и nulm соответственно 1112744, 1112745 и 1112746 в системе base 36.

Таблица сравнения

ФункцияparseIntparseFloatNumberBigInt
Игнорирует пробелы
.map(FN)☑️
Поддерживает аргумент radix
Бинарные/восьмеричные/шестнадцатеричные литералы
Недопустимые символы 42 oh no4242NaNSyntaxError

Как у вас получилось? 🧐

Нужен перерыв после такой дозы бинарных данных?
Пфф, помните: делайте перерыв после навыков!

Загляните в мой зал и разберите ещё несколько задач! 💪