您可以使用标准方法来完成。您可以定义一个clamp
实用函数:
/**
* Returns a number whose value is limited to the given range.
*
* Example: limit the output of this computation to between 0 and 255
* (x * 255).clamp(0, 255)
*
* @param {Number} min The lower boundary of the output range
* @param {Number} max The upper boundary of the output range
* @returns A number in the range [min, max]
* @type Number
*/
Number.prototype.clamp = function(min, max) {
return Math.min(Math.max(this, min), max);
};
(虽然扩展语言内置功能通常不被看好)
这是一个不那么“数学”取向的方法,但应该也可以工作。这种方法暴露了 <
/ >
的测试(可能比最小/最大值更易懂),但真正是否可读取,这取决于您所指的含义。
function clamp(num, min, max) {
return num <= min
? min
: num >= max
? max
: num
}
Math.random()
调用的开销,这种简单方法会快10倍。 - mindplay.dk一个简单的方法是使用
Math.max(min, Math.min(number, max));
你可以明显地定义一个包装这个功能的函数:
function clamp(number, min, max) {
return Math.max(min, Math.min(number, max));
}
起初,这个答案还将上面的函数添加到全局的 Math
对象中,但那是过去时代的遗物,因此已被移除(感谢 @Aurelio 的建议)。
prototype
非常优雅。 - MaxArtMath.max(min, Math.min(number, max))
(相关部分)仍然有效并值得点赞,因此@CAFxX是否考虑编辑答案并避免原型突变?我认为一些你会得到的赞被转移到了这个答案。 - AurelioMath.min(Math.max(MIN, VALUE), MAX)
,这样更容易记住:min+max
函数和 min value max
参数。 - Alex Yaroshevich我不想给你一个“只用库”的答案,但是如果你使用的是Lodash,你可以使用.clamp
函数:
_.clamp(yourInput, lowerBound, upperBound);
因此:
_.clamp(22, -10, 10); // => 10
以下是它的实现,取自 Lodash 源代码:
/**
* The base implementation of `_.clamp` which doesn't coerce arguments.
*
* @private
* @param {number} number The number to clamp.
* @param {number} [lower] The lower bound.
* @param {number} upper The upper bound.
* @returns {number} Returns the clamped number.
*/
function baseClamp(number, lower, upper) {
if (number === number) {
if (upper !== undefined) {
number = number <= upper ? number : upper;
}
if (lower !== undefined) {
number = number >= lower ? number : lower;
}
}
return number;
}
npm i --save lodash.clamp
number === number
的目的是什么?它总是评估为 true
吗? - Jivan PalNaN
时,表达式 number === number
的结果为 false。在处理数字逻辑时,通常需要处理这种情况。而 Object.is(number, number)
始终返回 true。 - RafiisNaN
而非使用 ===
呢?哈哈 - Justin如果您能使用ES6箭头函数,也可以使用部分应用程序方法:
const clamp = (min, max) => (value) =>
value < min ? min : value > max ? max : value;
clamp(2, 9)(8); // 8
clamp(2, 9)(1); // 2
clamp(2, 9)(10); // 9
or
const clamp2to9 = clamp(2, 9);
clamp2to9(8); // 8
clamp2to9(1); // 2
clamp2to9(10); // 9
如果您不想定义任何函数,那么像Math.min(Math.max(x, a), b)
这样写也不错。
将三元操作扩展为if/else,缩小后与三元操作等效但不牺牲可读性。
const clamp = (value, min, max) => {
if (value < min) return min;
if (value > max) return max;
return value;
}
最小化后的文件大小为35字节(如果使用function
,则为43字节):
const clamp=(c,a,l)=>c<a?a:c>l?l:c;
同时,根据你使用的性能工具或浏览器不同,无论是基于数学实现还是三元实现,都会得到不同的结果。如果两者大致相同,则应选择易读性更好的实现。
var clamp = (...v) => v.sort((a,b) => a-b)[1];
clamp(100,-3,someVar);
我最喜欢的:
[min,x,max].sort()[1]
[1,5,19].sort()[1]
返回的是 19。可以通过这种方式修复:[min,x,max].sort(function(a, b) { return a - b; })[1]
,但这样就不那么简洁明了了。此外,当频繁使用时,创建一个新数组来比较三个数字可能会影响性能。 - kayahr[min, x, max].sort((a,b) => a-b)[1]
。 - zaius
Number.prototype
)是不可取的。请参见“不良实践:扩展本机原型” https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain - broofaconst clamp =(num,min,max)=> Math.min(Math.max(num,min),max)
。 - AurelioMath
而不是Number
。 - vsync