Почему Math.pow() (иногда) не равно ** в JavaScript?

Я только что открыл функцию ECMAScript 7 a**b в качестве альтернативы для Math.pow(a,b) (Справочник по MDN) и наткнулся на обсуждение в этот пост, в котором они, по-видимому, ведут себя по-другому. Я тестировал его в Chrome 55 и могу подтвердить, что результаты отличаются.

Math.pow(99,99) возвращает 3.697296376497263e+197

тогда

99**99 возвращает 3.697296376497268e+197

Таким образом, запись разницы Math.pow(99,99) - 99**99 приводит к -5.311379928167671e+182.

До сих пор можно было сказать, что это просто другая реализация, но обертывание ее в функцию ведет себя иначе:

function diff(x) {
  return Math.pow(x,x) - x**x;
}

вызов diff(99) возвращает 0.

Почему это происходит?

Как отметил xszaboj, это можно сузить до этой проблемы:

var x = 99;
x**x - 99**99; // Returns -5.311379928167671e+182

Ответ 1

99**99 оценивается во время компиляции ( "постоянное складывание" ), а компилятор pow/a > отличается от runtime one. При оценке ** во время выполнения результаты идентичны с Math.pow - неудивительно, поскольку ** на самом деле скомпилирован для вызова Math.pow:

console.log(99**99);           // 3.697296376497268e+197
a = 99, b = 99;
console.log(a**b);             // 3.697296376497263e+197
console.log(Math.pow(99, 99)); // 3.697296376497263e+197