JavaScript Exponentiation: ** Operator vs Math.pow (BigInt, precedence, edge cases)

Exponentiation in JavaScript with the ** power operator and Math.pow: numbers, BigInt, right-associativity, unary minus precedence, NaN ** 0, **= compound assignment, and when to prefer Math.pow on older engines. Each section opens with a short explainer for readers and search; output is summarized after runnable snippets.

Published

Updated

Read time 5 min read

Reviewed byDeepak Prasad

JavaScript Exponentiation: ** Operator vs Math.pow (BigInt, precedence, edge cases)

Exponentiation means raising a base to an exponent—for example, raising 4 to the third power yields 64. In modern JavaScript you usually express that with the ** operator, or with Math.pow(base, exponent) when you want a function call or need compatibility with very old engines. For more patterns around powers and edge cases, see JavaScript Math.pow and related topics.

This guide covers **, Math.pow, BigInt rules, right-associativity, the unary-minus gotcha, and a couple of edge cases from the spec.

Tested on: Node.js v20.18.2. A short note after each snippet states the values you should see.


Quick reference

Skim this when you are choosing between the ** power operator and Math.pow, or when you need BigInt-safe exponentiation in JavaScript.

Use this table for exponentiation javascript: numbers vs BigInt and parsing pitfalls.

Tool Numbers BigInt Notes
x ** y Yes Yes if both are BigInt Right-associative; unary - needs () on base
Math.pow(x, y) Yes No (throws on BigInt) Works on older engines without **

1. From repeated multiplication to ``

The binary ** operator (also called the JavaScript power operator) raises the left operand to the right exponent. For whole-number powers it replaces long * chains and reads clearly in formulas and interview-style javascript exponentiation snippets.

javascript
let repeated = 4 * 4 * 4;
let operator = 4 ** 3;
console.log(repeated);
console.log(operator);
Output

Both lines print 64.


2. Exponentiation (``) and BigInt

BigInt exponentiation uses the same ** token (MDN: exponentiation operator): when both operands are BigInt, the result is a BigInt. Mixing 2n with 2 throws TypeError. Math.pow only accepts Number values—never pass BigInt without converting first.

javascript
const big = BigInt(345) ** BigInt(3);
console.log(big);
Output

You should see 41063625n (a BigInt literal suffix).

javascript
try {
  console.log(Math.pow(2n, 2));
} catch (e) {
  console.log(e.name + ": " + e.message.split("\n")[0]);
}
Output

The catch logs a TypeError about converting BigInt to number—Math.pow only accepts numbers.

javascript
try {
  console.log(2n ** 2);
} catch (e) {
  console.log(e.name);
}
Output

Mixing 2n with 2 throws TypeError—operands must both be BigInt or both be numbers after coercion rules.

Use 2n ** 2n (or convert explicitly) when you need BigInt powers.


3. Fractional exponents (still numbers)

Fractional powers—roots and non-integer exponents—stay on the Number type: ** follows the same floating-point rules as Math.pow, so expect tiny rounding differences when you compare javascript power operator results across engines or log them at full precision.

javascript
console.log(4 ** 3.3);
Output

You should see a floating-point value near 97.00586025666546.


4. Negative base: parenthesize

This is the most common operator precedence mistake with javascript exponentiation: the parser applies ** before unary minus on a bare literal, so -2 ** 5 means -(2 ** 5). Parenthesize the base as (-2) ** 5 when you mean “negative number to a power.”

javascript
console.log((-2) ** 5);
Output

You should see -32.


5. Right-associativity (``)

Chained ** groups from the right, unlike + and *. Interview-style javascript exponentiation questions often test this—add parentheses when you mean (a ** b) ** c.

a ** b ** c is a ** (b ** c), not (a ** b) ** c.

javascript
console.log(2 ** 3 ** 2);
console.log(2 ** (3 ** 2));
console.log((2 ** 3) ** 2);
Output

Three lines: 512, 512, then 64—showing right-associativity of ** versus explicit grouping.


6. NaN 0 (special case)

The language carves out one odd case: raising NaN to the integer exponent 0 yields 1, not NaN. The same rule exists on Math.pow, so code that branches on NaN propagation still needs to treat this edge carefully.

javascript
console.log(NaN ** 0);
Output

Per the spec, this prints 1—the same special case documented for Math.pow(NaN, 0).


7. Compound assignment (=)

**= is the compound assignment form: it raises the existing variable on the left to the exponent on the right and assigns the result back—handy for accumulators, games, and numeric APIs where you would otherwise write x = x ** n.

javascript
let x = 2;
x **= 3;
console.log(x);
Output

After x **= 3, you should see 8.


8. Math.pow (numbers only)

Use Math.pow(base, exponent) when you want a normal function call (easy to pass as a callback), when a linter or style guide discourages **, or when you must run on very old JavaScript engines that predate the ** operator. Arguments are always coerced toward Number; BigInt inputs throw.

javascript
console.log(Math.pow(4, 5));
console.log(Math.pow(6, -2));
console.log(Math.pow(-2, 5));
Output

Three lines: 1024, the repeating decimal for 6 ** -2, and -32 for a negative base passed as a normal argument.

Math.pow(-2, 5) does not need extra parentheses on the base because the base is a normal function argument, not a unary-expression parsing edge case.


Summary

  • ** is concise and supports BigInt when both operands are BigInt; watch precedence with unary -.
  • ** is right-associative: add parentheses when you mean (a ** b) ** c.
  • Math.pow is numbers-only; use it when targeting engines without **.
  • NaN ** 0 and Math.pow(NaN, 0) yield 1 by spec.

References

MDN references for the exponentiation operator, Math.pow, and precedence.


Frequently Asked Questions

1. What is the javascript power operator?

The infix operator ** raises the left operand to the right operand, for example 2 ** 10 === 1024. It was added in ES2016 and is documented on MDN as the exponentiation operator.

2. Should I use ** or Math.pow for exponentiation javascript code?

For plain numbers they are equivalent for many cases. Use ** for concise syntax and BigInt exponentiation when both operands are BigInts. Use Math.pow when you must support environments so old they lack **, or when you prefer a function call style.

3. Can I mix BigInt and number with **?

No. If one operand becomes a BigInt and the other a number after coercion, JavaScript throws TypeError. Use explicit conversions such as Number(2n) ** 2 or 2n ** 2n.

4. Why does -2 ** 5 throw or parse oddly?

Unary minus has lower precedence than **, so -2 ** 5 is parsed as -(2 ** 5). To raise a negative base, parenthesize the base: (-2) ** 5.

5. Is 2 ** 3 ** 2 equal to 64?

No. ** is right-associative, so 2 ** 3 ** 2 is 2 ** (3 ** 2) === 2 ** 9 === 512. Use parentheses (2 ** 3) ** 2 for 64.

6. What is NaN ** 0 in JavaScript?

NaN ** 0 and Math.pow(NaN, 0) both return 1; it is a special case where NaN does not propagate.
Olorunfemi Akinlua

Boasting over five years of experience in JavaScript, specializing in technical content writing and UX design. With a keen focus on programming languages, he crafts compelling content and designs …