JavaScript зарисовки в стиле WTF

Browsers


В JS есть оператор возведения в степень. Появился он в JavaScript относительно недавно (хотя с учетом скорости развития JS можно сказать что и давно). Пример использования:

Math.pow(2,2) === 2**2

Но, эти операторы не совсем эквивалентны. И вот вам пример:

Math.pow(99,99); // -> 3.697296376497263e+197
99 ** 99; // -> 3.697296376497268e+197
// следовательно
Math.pow(99,99) === 99**99 // false

Что за фигня? Опять этот ЖабаСкрипт косячит? Разные значения!

Но вдруг вы встречаете такой код:

const pow = num => num ** num
const num = 99
num ** num - pow(99) === 0 // true

И тут вы говорите: чоооо? В смысле? Ээээ… Перепроверяете:

void function (num = 99) {
console.log((num ** 99) === Math.pow(99,99)) // true
}()

Да что такое?

Короче, через какое-то время вы дойдете до того, что есть 2 вида выполнения кода: runtime и compiletime.

Это ошибка в V8 и проявляется она в браузере Chrome и Opera (это кстати тема к вопросу про монополизм и единый движок :)).

Оператор “**” вычисляется во время компиляции, что дает другой результат, чем результат во время выполнения. В Firefox и Safari ошибки нет.

Node.js и Deno

Deno — это экспериментальный молодой проект, альтернатива Node.js со встроенным TypeScript рантаймом.

И тут меня ждал сюрприз. В ноде есть ошибка, в то время как в Deno ее нет! Но у меня ест предположение: так как в Deno используется TS, то код оборачивается в некий рантайм, который как раз и компилируется. Поэтому то, что кажется выполняется в рантайме, на самом деле выполняется в компайле.


Детали бага “Math.pow and ** not equal”

Можно узнать по ссылке https://bugs.chromium.org/p/v8/issues/detail?id=5848

Информация актуальна на 22.02.2019+-. Это должны пофиксить. Как баг пофиксят, статья аннигилируется