en.javascript.info/1-js/6-objects-more/2-object-conversion/5-sum-many-brackets/solution.md
2015-01-14 10:23:45 +03:00

59 lines
No EOL
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Подсказка
Чтобы `sum(1)`, а также `sum(1)(2)` можно было вызвать новыми скобками -- результатом `sum` должна быть функция.
Но эта функция также должна уметь превращаться в число. Для этого нужно дать ей соответствующий `valueOf`. А если мы хотим, чтобы и в строковом контексте она вела себя так же -- то `toString`.
# Решение
Функция, которая возвращается `sum`, должна накапливать значение при каждом вызове.
Удобнее всего хранить его в замыкании, в переменной `currentSum`. Каждый вызов прибавляет к ней очередное значение:
```js
//+ run
function sum(a) {
var 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` срабатывает только один раз. Она возвращает функцию `f`.
Затем, при каждом запуске функция `f` добавляет параметр к сумме `currentSum`, хранящейся в замыкании, и возвращает сама себя.
**В последней строчке `f` нет рекурсивного вызова.**
Вот так была бы рекурсия:
```js
function f(b) {
currentSum += b;
return f(); // <-- подвызов
}
```
А в нашем случае, мы просто возвращаем саму функцию, ничего не вызывая.
```js
function f(b) {
currentSum += b;
return f; // <-- не вызывает сама себя, а возвращает ссылку на себя
}
```
Эта `f` используется при следующем вызове, опять возвратит себя, и так сколько нужно раз. Затем, при использовании в строчном или численном контексте -- сработает `toString`, который вернет текущую сумму `currentSum`.