假设我正在开发一个导出clamp()
函数的JavaScript库,
将数字限制在给定范围内。
export function clamp(n, min, max) {
return Math.min(Math.max(n, min), max);
}
但如果min
大于max
,此功能将失败。有两种解决方案
这似乎是明智的。
首先,该函数可以返回NaN
:
export function clamp(n, min, max) {
return min <= max ? Math.min(Math.max(n, min), max) : NaN;
}
其次,该函数可能抛出异常:
export function clamp(n, min, max) {
if (min > max) {
throw new RangeError('min may not be greater than max');
}
return Math.min(Math.max(n, min), max);
}
在这种情况下,哪种解决方案最好?
我将尝试回答我自己的问题,但我肯定会接受更好的问题 之一。
答案 0 :(得分:1)
此处需要考虑三个问题:如果用户需要一些输入,该怎么办? 无效?如果无效输入是无意的,该怎么办?什么样的模式 通常在语言中找到?
用户可能希望某些输入无效。如果函数返回NaN
,则这些情况很容易处理。
let values = [[2, 4, 6], [3, 5, 1], [7, 5, 9]];
let clamped = values.map(args => clamp(...args)).filter(n => !isNaN(n));
console.log(clamped); // [4, 7]
如果函数抛出异常,则用户必须使用a
try...catch
statement,这将更加冗长,性能更低。或者她
可以在应用clamp()
之前过滤掉无效输入,但是然后她
必须确切地知道哪种输入是无效的,哪些可能是无效的
比这个例子更复杂。
这显然是支持NaN
选项的一点。
如果该功能,部分用户的正版错误将更容易调试 抛出一个例外。例如,用户可能很容易犯错误 这样:
clamp(-4, 0, -10);
如果上面要返回NaN
,调试可能是噩梦,特别是在
一个包含大量其他内容的大型代码库。如果功能是
抛出异常,用户会看到:
RangeError: min may not be greater than max
at clamp ...
更简单。这显然是throw
的胜利。
所以我们有一个平局。我们最好的办法是问自己,WWJD(JavaScript会是什么?
做)?例如,当我们将负数传递给Math.sqrt()
时会发生什么?
console.log(Math.sqrt(-4)); // NaN
返回NaN
。这是打破平局。 JavaScript程序员会期望
如果输入无效,则返回NaN
这样的函数。他们会的
用于处理源自此行为的错误,如果不是,
然后他们最好习惯它。
所以请返回NaN
。