103

I want to limit a number between two values, I know that in PHP you can do this:

$number = min(max(intval($number), 1), 20);
// this will make $number 1 if it's lower than 1, and 20 if it's higher than 20

How can I do this in javascript, without having to write multiple if statements and stuff like that? Thanks.

Gil Epshtain
  • 8,670
  • 7
  • 63
  • 89
Alexandra
  • 1,033
  • 2
  • 7
  • 4

9 Answers9

221

like this

var number = Math.min(Math.max(parseInt(number), 1), 20);

#Live Demo:

function limitNumberWithinRange(num, min, max){
  const MIN = min ?? 1;
  const MAX = max ?? 20;
  const parsed = parseInt(num)
  return Math.min(Math.max(parsed, MIN), MAX)
}

alert(
  limitNumberWithinRange(  prompt("enter a number")   )
)
Yairopro
  • 9,084
  • 6
  • 44
  • 51
Govind Malviya
  • 13,627
  • 17
  • 68
  • 94
  • do Javascript has as `intval(num)` function. Cause I know only `parseInt(num)`? – Harry Joy Apr 30 '11 at 15:34
  • I dont know about php sorry I edited that I consider it as User defined function – Govind Malviya Apr 30 '11 at 15:36
  • 3
    Now our answers are identical so I'm deleting mine. – Harry Joy Apr 30 '11 at 15:42
  • thanks Joy for telling me about intval in php. and thanks for providing chance to me.. – Govind Malviya Apr 30 '11 at 15:46
  • 7
    Don't use `parseInt` unless you know what you are doing, e.g. `parseInt(1e300) === 1`. Just use `Math.min(Math.max(number, 1), 20)`. – Oriol Feb 05 '16 at 23:51
  • Isn't this backwards? As written, the number is maximum 1, and minimum 20, no? – Sandwich Jul 31 '16 at 22:02
  • 1
    @Sandwich Let's pay attention to `Math.max(number, 1)`. It's the maximum value among `number` and `1`. So it's `number` when `number > 1`, and it's `1` when `number <= 1`. i.e. it is always greater than or equals to `1`, no matter what `number` is, as long as `number` is numeric(`Math.max` can return `NaN` when `number` is not numeric.); the **`Math.max` sets the minimum limit** to `1`. And the **`Math.min` sets the maximum limit** to `20` in the same way. – Константин Ван Aug 05 '16 at 19:10
  • 2
    @Sandwich Remember, `Math.min` and `Math.max` are **not** `Math.setMinimumLimit` and `Math.setMaximumLimit`. Don't be confused. – Константин Ван Aug 05 '16 at 19:16
  • You will get unexpected results when running ```limitNumberWithinRange(num, 0, 42)```. In other words: min/max can't be set to 0 with this code. – Chen Eshchar Sep 20 '22 at 11:25
  • I googled this problem because I was having trouble naming my function. `limitNumberWithinRange` is a good name, i'm going to use it – Ro Milton Aug 23 '23 at 23:24
36

You have at least two options:

You can use a pair of conditional operators (? :):

number = number > 100 ? 100 : number < 0 ? 0 : number;

Or you can combine Math.max and Math.min:

number = Math.min(100, Math.max(0, number));

In both cases, it's relatively easy to confuse yourself, so you might consider having a utility function if you do this in multiple places:

function clamp(val, min, max) {
    return val > max ? max : val < min ? min : val;
}

Then:

number = clamp(number, 0, 100);
cutemachine
  • 5,520
  • 2
  • 33
  • 30
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
18

Use lodash's clamp method:

_.clamp(22, 1, 20) // Outputs 20

Neuron
  • 5,141
  • 5
  • 38
  • 59
Gregory Bolkenstijn
  • 10,003
  • 7
  • 36
  • 38
14

Needs no further explanation:

function clamp(value, min, max) {
    return Math.min(Math.max(value, min), max);
}
Neuron
  • 5,141
  • 5
  • 38
  • 59
  • Would this work for negative numbers aswell such as transform -xdeg? – Ryan Stone Oct 29 '20 at 10:41
  • @RyanStone what do you mean by "transform -xdeg"? It does work for negative values as well, yes. You can call `clamp(-5, -1, 1)` and it will return `-1`. – Neuron Oct 29 '20 at 11:04
  • was meaning to use it in Css Transform:rotateX(); which takes in negative values.. Via Javascript – Ryan Stone Oct 29 '20 at 17:42
9

Quote from this answer:

Update for ECMAScript 2017:

Math.clamp(x, lower, upper)

But note that as of today, it's a Stage 1 proposal. Until it gets widely supported, you can use a polyfill.

Neuron
  • 5,141
  • 5
  • 38
  • 59
Rafe
  • 1,937
  • 22
  • 31
2

One Liners

const clamp = (num, min, max) => num > max ? max : num < min ? min : num
const minmax = (num, min, max) => Math.min(Math.max(num, min), max)

Benchmark

Browser clamp() minmax() Result
Chrome 976,066,844 ops/s 971,704,488 ops/s clamp() 0.45% faster
Firefox 872,108,437 ops/s 1,358,476,166 ops/s minmax() 35.8% faster
Edge 958,554,747 ops/s 936,113,887 ops/s clamp() 2.34% faster

JsBench https://jsbench.me/qhl99e1thl/1

In case of firefox minmax() is much faster in compare to others. Though in chrome and Edge clamp() is faster than minmax() but difference is ignorable. So, my opinion is to use minmax() according to the benchmark.

Jawad Ahbab
  • 1,462
  • 1
  • 19
  • 31
1

Use Math.min and Math.max.

Femaref
  • 60,705
  • 7
  • 138
  • 176
1

I will share my robust function to enforce whole numbers (because of the integer tag), it has features like optional min/max parameters and -0 protection:

function toInt(val, min, max){
    val=(val*1 || 0);
    val=(val<0 ? Math.ceil(val) : Math.floor(val));

    min*=1;
    max*=1;

    min=((Number.isNaN(min) ? -Infinity : min) || 0);
    max=((Number.isNaN(max) ? Infinity : max) || 0);

    return Math.min(Math.max(val, min), max);
}

Some quick notes:

  • The (... || 0) behind the scenes is dealing with -0 to change it to 0, which is almost always what you want.
  • The min and max parameters are optional. When blank or invalid values are passed, they will turn into -Infinity and Infinity so they silently don't interfere with Math.min() and Math.max().
  • You can change Number.isNaN(x) ECMAScript-6 to x!==x (results in true only for NaN) for more compatibility with really old browsers, but this is simply not necessarily anymore.
ajax333221
  • 11,436
  • 16
  • 61
  • 95
0

You could easily just extend Math by adding your own method...

ES6

Math.minmax = (value, min, max) => Math.min(Math.max(value, min), max);

ES5

Math.minmax = function(value, min, max){
    return Math.min(Math.max(value, min), max);
}
Paul Browne
  • 752
  • 1
  • 7
  • 14
  • 3
    PLEASE do not do this. extending built-in objects in this way credibly damages the standardization process. Just use a function. – Benny Powers Mar 14 '23 at 13:10