Найти в Дзене
Tominoff

А вы знали, что в JS есть два нуля? 🤯

Да-да, есть 0 и -0. И да, они равны друг другу (-0 === 0), но всё же не идентичны Object.is(0, -0) === false. Главный парадокс: -0 === 0 // true
1/-0 === -Infinity // а 1/0 === Infinity Где JS различает нули: Математические операции: assert.strict. equal(-0, 0) // Будет выброшена ошибка в тесте
Math.sign(-0) // -0 (да, не -1!)
Math.pow(-0, 3) // -0
Math.pow(-0, 2) // 0 Тригонометрия (сохраняет знак): Math.atan2(-0, 1) // -0
Math.sin(-0) // -0 Специальные проверки: Object.is(0, -0) // false Во всех прочих случаях, JS плевать на знак нуля: `${-0}` // -> "0"
JSON.stringify(-0) // "0"
Math.log(-0) // -Infinity (как и для +0)
[0, -0].sort() // [0, -0] (порядок сохраняется)
[-0].includes(0) // true, как и [0].includes(-0)
parseFloat(-0) // 0 Когда это может оказаться полезно? Да фиг его знает на самом деле. Т.к. ведут себя эти нули одинаково в 99.99% случаев - я не смог придумать реальный кейс для этого. Единственная функция, которая может опираться на ра

Да-да, есть 0 и -0.

И да, они равны друг другу (-0 === 0), но всё же не идентичны Object.is(0, -0) === false.

Главный парадокс:

-0 === 0 // true
1/-0 === -Infinity // а 1/0 === Infinity

Где JS различает нули:

Математические операции:

assert.strict. equal(-0, 0) // Будет выброшена ошибка в тесте
Math.sign(-0) // -0 (да, не -1!)
Math.pow(-0, 3) // -0
Math.pow(-0, 2) // 0

Тригонометрия (сохраняет знак):

Math.atan2(-0, 1) // -0
Math.sin(-0) // -0

Специальные проверки:

Object.is(0, -0) // false

Во всех прочих случаях, JS плевать на знак нуля:

`${-0}` // -> "0"
JSON.stringify(-0) // "0"
Math.log(-0) // -Infinity (как и для +0)
[0, -0].sort() // [0, -0] (порядок сохраняется)
[-0].includes(0) // true, как и [0].includes(-0)
parseFloat(-0) // 0

Когда это может оказаться полезно?

Да фиг его знает на самом деле. Т.к. ведут себя эти нули одинаково в 99.99% случаев - я не смог придумать реальный кейс для этого.

Единственная функция, которая может опираться на разницу между 0 / -0 - Math.atan2. Это можно использовать для определения направления движения по единичной окружности:

// Подход к точке (0,0) с разных сторон:
Math.atan2(0, 0) // 0 (подход по положительной оси X)
Math.atan2(-0, 0) // -0 (подход по отрицательной оси X)

// Подход к точке (0,0) с разных сторон оси Y:
Math.atan2(0, -0) // π (3.14...) // справа от оси Y
Math.atan2(-0, -0) // -π (-3.14...) // слева от оси Y

Вообще в atan2 значения 0 и -0 тоже конечно выглядят как сова на глобусе (ну камон, кому вообще может понадобиться нулевой вектор?), тем не менее стоит учитывать этот факт.

Я могу порекомендовать лишь при разработке любых счётных функций не преобразовывать -0 к 0 нарочно и помнить об этом нюансе при покрытии тестами.

📌 Если хотите больше таких разборов — в моём Telegram их не так много 😅. Зато есть кусочки кода, баги и мысли вслух.