돌아가기

임의의 수만큼 있는 괄호를 이용해 합계 구하기

중요도: 2

다음과 같이 작동하는 함수 sum을 만들어보세요.

sum(1)(2) == 3; // 1 + 2
sum(1)(2)(3) == 6; // 1 + 2 + 3
sum(5)(-1)(2) == 6
sum(6)(-1)(-2)(-3) == 0
sum(0)(1)(2)(3)(4)(5) == 15

힌트: 해당 함수 내부에서 쓸 수 있는 객체-원시형으로의 형 변환을 직접 구현해야 할 수도 있습니다.

테스트 코드가 담긴 샌드박스를 열어 정답을 작성해보세요.

  1. sum은 함수를 반환해야만 이 모든 것이 의도한 대로 동작합니다.
  2. sum이 반환하는 함수는 호출될 때마다 현재 값을 메모리에 저장하고 있어야 합니다.
  3. 함수는 == 를 만났을 때 숫자가 되어야 합니다. 함수는 객체이므로 객체를 원시형으로 변환하기 챕터에서 설명한 것처럼, 객체-원시형으로의 형 변환이 일어날 텐데, 이때 메서드를 직접 구현해 원하는 대로 객체-원시형으로의 형 변환이 일어나게 할 수 있습니다.

답안은 아래와 같습니다.

function sum(a) {

  let currentSum = a;

  function f(b) {
    currentSum += b;
    return f;
  }

  f.toString = function() {
    return currentSum;
  };

  return f;
}

alert( sum(1)(2) ); // 3
alert( sum(5)(-1)(2) ); // 6
alert( sum(6)(-1)(-2)(-3) ); // 0
alert( sum(0)(1)(2)(3)(4)(5) ); // 15

함수 sum은 실제로 한 번만 동작한다는 사실에 주목하시기 바랍니다. 함수 sum은 함수 f를 반환합니다.

이어지는 호출에서 함수 f는 매개변수를 currentSum에 추가하고 자신을 반환합니다.

f의 마지막 줄에는 재귀가 없습니다.

재귀가 있었다면 아래와 같이 생겼을 겁니다.

function f(b) {
  currentSum += b;
  return f(); // <-- 재귀 호출
}

위 함수 f는 호출 없이 자기 자신을 그대로 반환합니다.

function f(b) {
  currentSum += b;
  return f; // <-- 자신을 호출하지 않고 반환만 합니다.
}

이렇게 자기 자신을 호출하지 않고 반환만 하면 다음 호출에서 함수 f를 사용할 수 있고, 자기 자신을 또다시 반환해 원하는 만큼 이 과정을 반복할 수 있습니다. toStringcurrentSum 을 반환해주므로 반환된 함수(객체)를 숫자 혹은 문자열로도 사용할 수 있죠. Symbol.toPrimitivevalueOf를 사용해 객체를 숫자나 문자열로 변환할 수도 있습니다.

function sum(a) {

  let currentSum = a;

  function f(b) {
    currentSum += b;
    return f;
  }

  f.toString = function() {
    return currentSum;
  };

  return f;
}

테스트 코드가 담긴 샌드박스를 열어 정답을 확인해보세요.