Следующая функция, предложенная "Дугом Крокфордом: JavaScript: хорошие детали". отлично работает.
var fibonacci = function () {
var memo = [0, 1];
var fib = function (c) {
console.debug(memo, c, memo[c]);
result = memo[c];
if (typeof result !== 'number'){
result = fib(c - 1) + fib(c - 2);
memo[c] = result;
}
return result;
};
return fib;
}();
console.log(fibonacci(3));
Но давайте подробно рассмотрим, что происходит с линией 4
console.debug(memo, c, memo[c]);
Он показывает следующий результат, который противоположный тому, что ожидалось.
memo, c, memo[c]
[0, 1, 1, 2] 3 undefined //contradictory behavior because I expect to have memo = [0, 1]
[0, 1, 1, 2] 2 undefined //contradictory behavior
[0, 1, 1, 2] 1 1
[0, 1, 1, 2] 0 0
[0, 1, 1, 2] 1 1
2
Некоторые идеи?
Это проблема с выходом консоли Chrome. Кажется, Chrome динамически обновляет вывод, чтобы каким-то образом отразить содержимое массива. Если вы запустите его в Firebug, выход будет выглядеть следующим образом:
[0, 1] 3 undefined
[0, 1] 2 undefined
[0, 1] 1 1
[0, 1] 0 0
[0, 1, 1] 1 1
2
Также имеет смысл, когда вы пытаетесь пройти через код в своей голове: console.debug
- это первый оператор в fib
. В первый раз вызывается fib
, memo
- [0, 1]
, поскольку никаких изменений в массиве не было. c
3
, поэтому вы получаете undefined
. Таким образом, при первом вызове memo
не может быть [0, 1, 1, 2]
независимо от того, что показывает консоль.
Некоторые консоли JavaScript похоже, показывают такое поведение (так или иначе), когда вы регистрируете ссылки на массивы или объекты. В этих случаях часто бывает лучше установить точки останова и пройти шаг за шагом.
Обновление: Кажется, Firebug исправил эту проблему (если она когда-либо существовала), но она все еще существует в свете Firebug.