Чтобы расширить то, что @Barmar написал в своем комментарии, в первом примере ваша внутренняя функция add ничего не возвращает, поэтому ее возвращаемое значение будет неопределенным. Следовательно, ответ остается ложным при каждом вызове «inner», и поэтому захваченная функция «addByTwo» вызывается все три раза. Вот почему вы получаете чередующийся номер, который представляет собой результат сложения, зарегистрированный в самом «add», и неопределенный, который является зарегистрированным возвращаемым значением. Вы исправляете это во втором примере, возвращая возвращаемое значение из 'add'.
Теперь я хотел бы отметить пару вещей, которые могут быть вам полезны.
1) Ваш второй пример все равно будет неудачным, если вы передадите -2 в первый раз, когда вы вызываете 'OnceFunc'. Зачем? Потому что это утверждение:
if (!answer) {
Проверяет, является ли ответ ложным, что равно 0 (-2 + 2). Вы можете решить эту проблему, проверив, не является ли ответ неопределенным.
2) Я не знаю, насколько вам нужно, чтобы это было гибким, но при использовании метода apply в вашей захваченной функции вам не нужно указывать аргументы для inner. Это означает, что передаваемая вами функция может принимать ноль, один или несколько аргументов.
Вот пример взлома вашего кода, когда передается -2 (как указано в пункте # 1):
function addByX(x) {
function add(y) {
return y + x;
}
return add;
}
var addByTwo = addByX(2);
function once(func) {
var answer;
function inner(x) {
if (!answer) {
answer = func(x);
return answer;
} else {
return answer;
}
}
return inner;
}
var onceFunc = once(addByTwo);
console.log(onceFunc(-2)); //should log 0
console.log(onceFunc(10)); //should log 0, but it won't
И здесь исправлено решение проблемы, упомянутой в # 1, и обеспечение гибкости, упомянутой в # 2:
function addByX(x) {
function add(y) {
return y + x;
}
return add;
}
function mult(a, b) {
return a * b;
}
var addByTwo = addByX(2);
function once(func) {
var answer;
function inner() {
if(typeof answer === 'undefined') {
answer = func.apply(null, arguments);
return answer;
} else {
return answer;
}
}
return inner;
}
var onceFunc = once(addByTwo);
console.log(onceFunc(-2)); // should log 0
console.log(onceFunc(10)); // should log 0, this time it will
console.log(onceFunc(9001)); // should log 0, and again it will
// this can also be re-used with a function that accepts multiple parameters (or none)
var onceFuncMult = once(mult);
console.log(onceFuncMult(3, 5)); // 15
console.log(onceFuncMult(8, 5)); // still 15
Надеюсь, что это полезно и предоставляет немного дополнительной информации, чтобы помочь вам в этом.