[javascript] 세그먼트에 숫자를 제한하는 가장 우아한 방법은 무엇입니까?

하자의 말 x, a그리고 b숫자입니다. x세그먼트의 경계에 모자 를 씌워야합니다 [a, b].

쓸 수는 Math.max(a, Math.min(x, b))있지만 읽기가 쉽지 않다고 생각합니다. 누구나 더 읽기 쉬운 방법으로 이것을 쓸 수있는 영리한 방법이 있습니까?



답변

당신이 그것을하는 방법은 꽤 표준입니다. 유틸리티 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;
}


답변

ECMAScript 2017 업데이트 :

Math.clamp(x, lower, upper)

그러나 현재로서는 1 단계 제안 입니다. 광범위하게 지원 될 때까지 polyfill을 사용할 수 있습니다 .


답변

Math.clip = function(number, min, max) {
  return Math.max(min, Math.min(number, max));
}


답변

이것은 “라이브러리 사용”대답이 아니라 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;
}

또한 Lodash는 단일 메소드를 독립형 모듈로 사용 가능하게하므로이 메소드 만 필요한 경우 나머지 라이브러리없이 설치하면됩니다.

npm i --save lodash.clamp


답변

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)는 경우처럼 작성하는 것이 그렇게 나쁘지 않습니다.