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.
let repeated = 4 * 4 * 4;
let operator = 4 ** 3;
console.log(repeated);
console.log(operator);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.
const big = BigInt(345) ** BigInt(3);
console.log(big);You should see 41063625n (a BigInt literal suffix).
try {
console.log(Math.pow(2n, 2));
} catch (e) {
console.log(e.name + ": " + e.message.split("\n")[0]);
}The catch logs a TypeError about converting BigInt to number—Math.pow only accepts numbers.
try {
console.log(2n ** 2);
} catch (e) {
console.log(e.name);
}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.
console.log(4 ** 3.3);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.”
console.log((-2) ** 5);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.
console.log(2 ** 3 ** 2);
console.log(2 ** (3 ** 2));
console.log((2 ** 3) ** 2);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.
console.log(NaN ** 0);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.
let x = 2;
x **= 3;
console.log(x);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.
console.log(Math.pow(4, 5));
console.log(Math.pow(6, -2));
console.log(Math.pow(-2, 5));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.powis numbers-only; use it when targeting engines without**.NaN ** 0andMath.pow(NaN, 0)yield1by spec.
References
MDN references for the exponentiation operator, Math.pow, and precedence.
