Skip to content

Latest commit

 

History

History
115 lines (82 loc) · 5.65 KB

README.md

File metadata and controls

115 lines (82 loc) · 5.65 KB

Math.clamp

A TC39 proposal to add Math.clamp: a function that constrains a value between an upper and lower bound.

Status

Stage: 0
Champion: Oliver Medhurst (@canadahonk)
Authors: Oliver Medhurst (@canadahonk), Richie Bendall (@richienb)
Last Presented: (unpresented)

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

...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 (see also the previous discussion on the order of options for CSS clamp.

The original proposal intended to have the min and max arguments optional and allowing null or undefined as values to mean no upper/lower bound; but following recent TC39 requirements, it was agreed among some delegates that it would be best to not do this, especially since Math.min/Math.max remains available for uses with a single bound.

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 supports -Infinity/Infinity to specify when there is no upper or lower bound, although Math.min/Math.max are also already available to use:

Math.clamp(5, 0, Infinity) === Math.max(5, 0) // 5
Math.clamp(-5, -Infinity, 10) === Math.min(-5, 10) // -5

If the minimum bound is larger than the maximum bound, it throws a RangeError to avoid possible developer confusion:

Math.clamp(10, 5, 0) // RangeError

It also correctly respects -0 if given:

Math.clamp(-2, -0, 10) // -0
Math.clamp(-0, -0, 10) // -0
Math.clamp(0, -0, 10) // 0

Specification

Implementations

Acknowledgements

Past work: