简体   繁体   English

javascript memoized fibonacci 递归函数中的缓存如何更新?

[英]How does the cache update in javascript memoized fibonacci recursive function?

Considering the following recursive Fibonacci function that's been optimized using memoization.考虑以下使用记忆优化的递归斐波那契函数。 No other code apart from this.除此之外没有其他代码。

function memoizeFibonacci(index, cache = []) {
    if (cache[index]) {
        return cache[index]
    } else {
        if (index < 3) return 1
        else {
            cache[index] = memoizeFibonacci(index - 1, cache) + memoizeFibonacci(index - 2, cache)
        }
    }
    console.log(cache)
    return cache[index];
}
memoizeFibonacci(6)

Can someone please explain how is the cache array updated?有人可以解释一下缓存数组是如何更新的吗? When viewing the console logs the cache seems to hold all the previous values from the resolved recursive functions.查看控制台日志时,缓存似乎保存了已解析递归函数中的所有先前值。 But to me, this doesn't make sense as the cache is not stored outside memoizeFibonacci so the scope should not allow this.但对我来说,这没有意义,因为缓存没有存储在 memoizeFibonacci 之外,所以范围不应该允许这样做。

Every nested recursive function adds its item when it resolves only during the chain of executions of the recursion.每个嵌套递归函数仅在递归执行链期间解析时添加其项。

console.log is asynchronous and probably shows repeatedly the final result. console.log是异步的,可能会重复显示最终结果。 There is no specification about how console.log work so it can act differently depending on the environment, it's I/O.没有关于console.log如何工作的规范,因此它可以根据环境采取不同的行动,它是 I/O。

Even if you make it work as expected in your environment, it can work differently for other user.即使您让它在您的环境中按预期工作,它对其他用户的工作方式也会有所不同。 An hypothesis based on the use of console in your algorithm is not correct.基于在算法中使用console的假设是不正确的。

Kyle Simpson references:凯尔辛普森参考:

This has nothing to do with closures.这与闭包无关。 This is simply passing the same array to nested recursive calls.这只是将相同的数组传递给嵌套的递归调用。

When you pass an array (or any object for that matter) to a function, the array is not copied, rather a reference to it is passed, so changing the array in the recursive call will affect the same array.当您将数组(或与此相关的任何对象)传递给函数时,不会复制该数组,而是传递对其的引用,因此在递归调用中更改数组将影响同一个数组。

Here is an example of what is basically happening:这是一个基本发生的事情的例子:

 function foo(arr) { arr[0] = "hello"; } let arr = []; foo(arr); console.log(arr); // changed because of the call to foo

Notice that the recursive calls to memoizeFibonacci is explicitly passing the cache object as the second parameter, so each recursive call is sharing the same array as the top-level call, and any changes to the cache object in the recursive calls is reflected in the top-level call aswell.请注意,对memoizeFibonacci的递归调用显式地将cache对象作为第二个参数传递,因此每个递归调用都与顶级调用共享相同的数组,并且递归调用中对cache对象的任何更改都反映在顶部级调用。

BTW, this type of memoization is not persistent, meaning that these two calls:顺便说一句,这种类型的记忆不是持久的,这意味着这两个调用:

memoizeFibonacci(6);
memoizeFibonacci(10);

don't share the same cache object.不要共享相同的cache对象。 They each use a different cache array that must be reconstructed from scratch rather than the call to memoizeFibonacci(10) using the cache object already constructed in the call to memoizeFibonacci(6) and appending to it.它们分别使用不同cache阵列必须从头开始,而不是呼叫被重构memoizeFibonacci(10)使用cache在调用已经构造的对象memoizeFibonacci(6)和附加到它。 A more efficient memoization makes use of closures like in this example: https://stackoverflow.com/a/8548823/9867451更有效的记忆方法使用闭包,如本例所示: https : //stackoverflow.com/a/8548823/9867451

Note: If you are asking why all the console.log(cache) print out the same exact filled array, that's because they are printing the same array, and the values you see in the console are not necessarily added at the point of the console.log .注意:如果您问为什么所有的console.log(cache)打印出完全相同的填充数组,那是因为它们打印的是相同的数组,并且您在控制台中看到的值不一定添加到console.logconsole.log Take a look at this other question: array.length is zero, but the array has elements in it .看看另一个问题: array.length is zero, but the array has elements in it To log exactly what's in the cache object at the time of the console.log , change it to:要准确记录console.logcache对象中的内容,请将其更改为:

console.log(JSON.stringify(cache));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM