Lodash _.clamp() method

Beginner
⏱️ 6 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.clamp(number, lower, upper) coerces inputs, applies the upper bound then the lower bound, and why reversed bounds need Math.min / Math.max first.
  • Why NaN is 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).
  • NaN propagation: 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

javascript
_.clamp(number, lower, upper)
  • number: value to clamp; coerced with toNumber.
  • lower / upper: inclusive ends in the usual case (lower <= upper); both are coerced with toNumber (invalid bounds become 0).
  • Returns: the clamped finite number, or NaN when number is NaN after coercion.
1

Docs-style numeric clamp

The textbook pattern: keep a value inside [lower, upper] when it overshoots either side.

javascript
import clamp from "lodash/clamp";

clamp(-10, -5, 5);
// => -5

clamp(10, -5, 5);
// => 5
Try it Yourself
2

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.

javascript
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
Try it Yourself
3

NaN and coercion

Numeric strings coerce; values that become NaN stay NaN because lodash skips the min/max branch when number !== number.

javascript
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
Try it Yourself

📋 _.clamp vs Math.min / Math.max

SituationNative_.clamp
Ordered bounds (lower <= upper)Math.min(upper, Math.max(lower, n))Same two-step cap-then-floor semantics
lower > upperMust swap manuallyStill no swap—pre-order with Math.min / Math.max
String inputsCoerces unpredictablyRuns through lodash toNumber
NaN valueNaN poisons comparisonsReturns 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

Validation

NaN is still invalid

Clamp does not pick a default inside the interval. Sanitize with Number.isFinite or _.toNumber + checks before trusting the result.

Intervals

Inclusive on both ends

Unlike _.inRange, both lower and upper are inclusive stops. Do not mix the mental models.

Bounds

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.

Types

Coercion surprises

Numeric-looking strings become numbers; garbage strings become NaN. Normalize user text explicitly when strict typing matters.

❓ FAQ

After coercion, a finite number is capped to upper, then raised to lower, when those bounds are defined. If number is NaN after coercion, lodash skips those steps and returns NaN.
Lodash does not swap them. _.clamp(5, 10, 0) caps 5 to upper 0 (getting 0), then raises to lower 10, yielding 10. For user-supplied min/max, compute lo = Math.min(lower, upper) and hi = Math.max(lower, upper) before calling clamp.
Only when lower <= upper. The lodash implementation always applies the upper bound first, then the lower bound, so reversed arguments do not match min(max(n, lower), upper). Pair with Math.min/Math.max on the bounds when order is unknown.
Bounds are coerced with toNumber like other arguments, so IEEE Infinity usually survives as a real endpoint (unlike helpers that funnel through toFinite). Typical open-ended clamps still behave intuitively; if you need stricter semantics, validate bounds yourself.
No. toNumber throws "Cannot convert a BigInt value to a number" before any clamping. Convert to Number yourself only if you accept possible truncation.
Use import clamp from "lodash/clamp"; for ESM or const clamp = require('lodash/clamp') in CommonJS.

Summary

  • Purpose: keep a number inside inclusive bounds after coercion when lower <= upper (or after you order the bounds yourself).
  • Remember: NaN in, NaN out; cap-to-upper then 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.
Did you know?

_.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).

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful