Awesome
Math.clamp
ECMAScript proposal and reference implementation for Math.clamp
.
Author: Richie Bendall
Champion: None
Stage: 0
Overview and motivation
A clamping function constrains a value between an upper and lower bound.
Our primary motivation is its usefulness and popularity in existing projects where it is often defined for the sake of readability. A common use is for animations and interactive content. For example, it helps to keep objects in-bounds during user-controlled movement by restricting the coordinates that it can move to (see the p5.js demo for its constrain
function). Projects tend to define a function that looks like clamp(number, min, max)
, either through:
- Chaining mathematical operators with if statements or ternary operators
function clamp(number, minimum, maximum) {
if (number < minimum) {
return minimum;
}
if (number > maximum) {
return maximum;
}
return number;
}
function clamp(number, minimum, maximum) {
return Math.min(Math.max(number, minimum), maximum);
}
Each of those examples require unnecessary boilerplate and are error-prone. For example, a developer only has to mistype a single operator or mix up a single variable name for the function to break. They also disregard the potential undefined behaviour that can occur when minimum is larger than maximum, or when only min
or max
is specified.
We name it the function clamp
, like how it is in other programming languages...
clamp
in CSSMath.Clamp
in C#std::clamp
in the C++ standard libraryclamp
forf32
andf64
in RustcoerceIn
in Kotlinclamp
in Dartclamp
in Rubyclamp
in Elm
...and userland implementations:
Another motivation is to bring parity with the CSS function of the same name, although it will have a different parameter order because of the slightly different use cases in each context (also see the previous discussion on the order of options for CSS clamp
.
Recognizing the usefulness and improved readability of only specifying either a min
or max
(i.e. Math.min(number, 5)
vs Math.clamp(number, undefined, 5)
), we consider also allowing null
or undefined
as values for min
and max
to semantically mean "no upper/lower bound". We consider this as opposed to Math.clampMin
and Math.clampMax
, or an option bag, to remain conventional to the language.
Examples
The proposed API allows a developer to clamp numbers like:
Math.clamp(5, 0, 10);
//=> 5
Math.clamp(-5, 0, 10);
//=> 0
Math.clamp(15, 0, 10);
//=> 10
It handles a larger minimum than maximum number, like how the CSS clamp()
function does.
// Minimum number is larger than maximum value
Math.clamp(10, 5, 0);
//=> 10
It supports null
/undefined
/-Infinity
/Infinity
to specify when there is no upper or lower bound:
Math.clamp(5, 0, null);
//=> 5
Math.clamp(5, undefined, 10);
//=> 5
Specification
Implementations
Acknowledgements
Specification and reference implementation inspired by: