Math.sign()
Returns 1, -1, 0, -0, or NaN indicating the sign of a number.
Math.sign(x)- Added in JavaScript ES2015
Parameters
| Parameter | Type | Description |
|---|---|---|
$x | number | A number whose sign is returned. Non-numbers are coerced first. |
Return value
number1 if x is positive, -1 if x is negative, 0 if x is positive zero, -0 if x is negative zero, and NaN otherwise.
Math.sign() reduces a number to its direction. It has five possible results, not three: 1, -1, 0, -0, and NaN.
When to reach for it
Anywhere direction matters more than magnitude. It makes a clean numeric comparator — arr.sort((a, b) => Math.sign(a - b)) — and it reads better than nested ternaries when branching on direction: scroll or swipe direction, whether a value is above or below a target, which way to step in a loop.
It also pairs with Math.abs() to build sign-preserving operations. Math.sign(x) * Math.round(Math.abs(x)) gives away-from-zero rounding; Math.sign(x) * Math.min(Math.abs(x), cap) caps a magnitude without flipping direction.
What trips people up
Zero. Math.sign(0) is 0 and Math.sign(-0) is -0, so a truthiness check like if (Math.sign(x)) treats both zeros as false — usually what you want, but not a way to distinguish them. And because 0 === -0, only Object.is() tells them apart.
The other one is coercion: Math.sign("foo") and Math.sign() return NaN rather than throwing, and NaN is neither positive nor negative, so a > 0 / < 0 branch on the result silently falls through to the else.
Example
When to use it
- Writing a numeric sort comparator as Math.sign(a - b)
- Detecting scroll or drag direction from a delta
- Preserving a value's sign while transforming its magnitude
- Choosing a step direction of +1 or -1 in a loop
Frequently asked questions
What does Math.sign() return?
It returns 1 for positive numbers, -1 for negative numbers, 0 for positive zero, -0 for negative zero, and NaN for anything that cannot be coerced to a number.
How do I check whether a number is positive or negative?
Use Math.sign(x) === 1 or Math.sign(x) === -1. Note that Math.sign(-0) === 0 is true because -0 === 0, so use Object.is if the zero's sign matters.
Is Math.sign() a good sort comparator?
Yes — Array.prototype.sort only looks at the sign of the returned value, so (a, b) => Math.sign(a - b) sorts numbers ascending and states the intent clearly.
More examples
As a sort comparator
sort only needs the sign of the comparator's return value, so Math.sign(a - b) is a correct and self-documenting comparator. It also guards against overflow-style surprises with very large differences, since the caller never sees the raw magnitude.
const nums = [10, -3, 7, 0, -8, 2];
console.log([...nums].sort((a, b) => Math.sign(a - b)));
// Sorting objects by a numeric field
const rows = [
{ name: "b", score: 5 },
{ name: "a", score: 12 },
{ name: "c", score: -1 },
];
rows.sort((x, y) => Math.sign(y.score - x.score));
console.log(rows.map((r) => r.name)); // ["a", "b", "c"]Preserving sign while changing magnitude
Splitting sign from magnitude lets you clamp or round the size of a value without flipping its direction. The last block shows the trap: Math.sign(undefined) is NaN, and since NaN fails every comparison the code reports "flat" for what was actually invalid input.
const capMagnitude = (x, cap) => Math.sign(x) * Math.min(Math.abs(x), cap);
console.log([15, -15, 4, -4].map((n) => capMagnitude(n, 10)));
// Away-from-zero rounding, unlike Math.round
const halfUp = (x) => Math.sign(x) * Math.round(Math.abs(x));
console.log(Math.round(-2.5), halfUp(-2.5)); // -2 -3
// NaN falls through a naive branch
const s = Math.sign(undefined);
console.log(s > 0 ? "up" : s < 0 ? "down" : "flat"); // "flat"
Discussion