Lodash _.clamp() method
What you’ll learn
- How
_.clamp(number, lower, upper)coerces inputs, applies the upper bound then the lower bound, and why reversed bounds needMath.min/Math.maxfirst. - Why
NaNis not “healed” into a finite value—and when to pair with _.toNumber(). - Everyday uses: sliders, indices, canvas coordinates, and API limits.
- Try each example in the editor (
?tryit=1,2,3) with Lodash from a CDN.
Prerequisites
Comfort with Math.min / Math.max and the Number methods hub; optional Math methods if you combine clamping with rounding.
- Numeric ordering: know when you want inclusive bounds on both ends (clamp) versus half-open ranges (_.inRange).
NaNpropagation: invalid math stays invalid unless you sanitize first.
Overview
_.clamp is the lodash answer to “keep this number inside a lane.” It coerces arguments with toNumber, caps n to upper, then raises it to lower—skipping those steps when n is NaN. Expect lower <= upper for intuitive results; lodash does not reorder reversed bounds for you.
UI safety rails
Volume, opacity, zoom, and scroll offsets stay inside min/max without repeating the same Math dance.
Order your bounds
If min/max can arrive flipped, wrap them with Math.min / Math.max before _.clamp—lodash will not fix lower > upper for you.
Tree-shakeable
Import lodash/clamp so bundlers drop the rest of Lodash.
Syntax
_.clamp(number, lower, upper) - number: value to clamp; coerced with
toNumber. - lower / upper: inclusive ends in the usual case (
lower <= upper); both are coerced withtoNumber(invalid bounds become0). - Returns: the clamped finite number, or
NaNwhennumberisNaNafter coercion.
Docs-style numeric clamp
The textbook pattern: keep a value inside [lower, upper] when it overshoots either side.
import clamp from "lodash/clamp";
clamp(-10, -5, 5);
// => -5
clamp(10, -5, 5);
// => 5 Reversed bounds (lodash does not swap)
Unlike _.inRange, _.clamp does not reorder lower and upper. It caps to upper first, then raises to lower, so reversed arguments are usually wrong—normalize with Math.min / Math.max when order is uncertain.
import clamp from "lodash/clamp";
// No swap: cap to upper (0), then floor to lower (10)
clamp(5, 10, 0);
// => 10
clamp(15, 10, 0);
// => 10
const lo = Math.min(10, 0);
const hi = Math.max(10, 0);
clamp(5, lo, hi);
// => 5 NaN and coercion
Numeric strings coerce; values that become NaN stay NaN because lodash skips the min/max branch when number !== number.
import clamp from "lodash/clamp";
console.log(clamp("12.6", 0, 10)); // 10 (string coerced)
console.log(Number.isNaN(clamp(NaN, 0, 100))); // true
console.log(Number.isNaN(clamp("x", 0, 10))); // true 📋 _.clamp vs Math.min / Math.max
| Situation | Native | _.clamp |
|---|---|---|
Ordered bounds (lower <= upper) | Math.min(upper, Math.max(lower, n)) | Same two-step cap-then-floor semantics |
lower > upper | Must swap manually | Still no swap—pre-order with Math.min / Math.max |
| String inputs | Coerces unpredictably | Runs through lodash toNumber |
NaN value | NaN poisons comparisons | Returns NaN without pretending it landed inside the range |
If you already know bounds are ordered and numeric, the native one-liner is fine. Reach for lodash when inputs are messy or you want documented coercion parity across Node and browsers.
Pitfalls to avoid
NaN is still invalid
Clamp does not pick a default inside the interval. Sanitize with Number.isFinite or _.toNumber + checks before trusting the result.
Inclusive on both ends
Unlike _.inRange, both lower and upper are inclusive stops. Do not mix the mental models.
Reversed lower / upper
_.inRange swaps endpoints; _.clamp does not. If inputs might be flipped, compute const lo = Math.min(a, b); const hi = Math.max(a, b); before clamping.
Coercion surprises
Numeric-looking strings become numbers; garbage strings become NaN. Normalize user text explicitly when strict typing matters.
❓ FAQ
Summary
- Purpose: keep a number inside inclusive bounds after coercion when
lower <= upper(or after you order the bounds yourself). - Remember:
NaNin,NaNout; cap-to-upperthen floor-to-lower—no automatic swap like_.inRange. - Next: Lodash _.inRange() for half-open range tests, the Number hub, or the official Lodash docs for _.clamp.
_.clamp coerces arguments with toNumber. Invalid bounds become 0; a non-finite number stays NaN and skips clamping. The core applies upper first (cap), then lower (floor)—it does not reorder reversed bounds (unlike _.inRange).
6 people found this page helpful
