关于“JavaScript - 好的部分”的解释示例(第 4.15 节)?

发布于 2024-09-25 10:37:56 字数 663 浏览 7 评论 0原文

JS 初学者 :) 需要对 Crockford 的书 部分中的代码片段进行解释4.15:

var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fundamental(shell, n);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};

var fibonacci = memoizer([0, 1], function (shell, n) {
    return shell(n - 1) + shell(n - 2);
});

问题:我们如何计算 fibonacci(15),如果是简单的 fibonacci(15) 调用,那么它具体是如何工作的?

感谢您的帮助。

Beginner in JS :) needs an explanation of code piece from Crockford's book, section 4.15:

var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fundamental(shell, n);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};

var fibonacci = memoizer([0, 1], function (shell, n) {
    return shell(n - 1) + shell(n - 2);
});

Question: How do we calculate fibonacci(15), and if it is simple fibonacci(15) call, then how it works in detail?

Thanks for help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

痴者 2024-10-02 10:37:56

这是一个 console.log() 带注释的版本,它尝试显示堆栈如何返回并将 (n-1)+(n-2) 的结果分配给每个相应递归调用的备忘录数组。还要记住堆栈以相反的顺序返回。因此,在记录的输出中,您将看到首先返回的最后一个调用:

var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fundamental(shell, n);
            console.log("Hence 'shell(n-1)+shell(n-2)' results in the assignment memo["+n+"]="+result);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};
var fibonacci = memoizer([0, 1], function (shell, n) {
    console.log("shell is called, and 'n' is equal to --> " + n + "\n" + "At this point shell(n-1)="+shell(n-1)+" AND shell(n-2)="+shell(n-2));
    return shell(n - 1) + shell(n - 2);    
});

Here's a console.log() annotated version which attempts to show how the stack returns and assigns the result of (n-1)+(n-2) to the memo array for each respective recursive call. Also remember that the stack returns in reverse order. So in the logged output you'll see the last call returned first:

var memoizer = function (memo, fundamental) {
    var shell = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
            result = fundamental(shell, n);
            console.log("Hence 'shell(n-1)+shell(n-2)' results in the assignment memo["+n+"]="+result);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};
var fibonacci = memoizer([0, 1], function (shell, n) {
    console.log("shell is called, and 'n' is equal to --> " + n + "\n" + "At this point shell(n-1)="+shell(n-1)+" AND shell(n-2)="+shell(n-2));
    return shell(n - 1) + shell(n - 2);    
});
一抹苦笑 2024-10-02 10:37:56

看起来您对为什么调用 fibonacci(15) 起作用感到困惑。
让我们简化一下代码(暂时忘记记忆)。

var m = function () {
    var s = function (n) {
        console.log(n);
    };
    return s;
}; 
var f = m();

基本上,我们将 f 设置为函数 m() 的返回值。在这种情况下,该返回值是一个函数。看,我们可以进一步将其简化为:

var f = function (n) { console.log(n); };

换句话说,我们将 f 设置为一个接受一个参数的函数。我们在 fibinacci 中做同样的事情例子。这就是调用 fibonacci(15) 起作用的原因。

It looks like you're confused about WHY the invocation fibonacci(15) works.
Let's simplify the code (forget about memoization for a second).

var m = function () {
    var s = function (n) {
        console.log(n);
    };
    return s;
}; 
var f = m();

Basically we are setting f to the return value of function m(). In this case, that return value is a function. See, we could simplify it further as:

var f = function (n) { console.log(n); };

In other words, we are setting f to be a function that takes in one parameter. We are doing the same thing in the fibinacci example. That is why the invocation fibonacci(15) works.

℡寂寞咖啡 2024-10-02 10:37:56

正如对您的问题的评论所建议的那样,如果您无法遵循书中的解释,您应该在调试器中浏览代码,以便更好地理解正在发生的情况。但我将向您简要概述正在发生的事情:

正在演示的是“记忆”,这是函数式编程中使用的常见优化技术。如果结果仅取决于传递给函数的参数,则称函数是纯函数。因此,如果一个函数是纯函数,您可以根据参数缓存结果 - 这种技术称为记忆化。如果一个函数的计算成本很高并且被多次调用,您就可以这样做。

用于演示这一点的经典示例(如此处)是生成斐波那契数。我不会详细介绍这些是如何计算出来的,但基本上,当你得到越来越高的数字时,你会越来越多地重复自己,因为每个数字都是根据前面的两个数字计算出来的。通过记住每个中间结果,您只需计算它们一次,从而使算法更快(当您在序列中走得更高时,速度会快得多)。

就这段代码而言,memoizer 采用两个参数 - “memo”,即缓存。在本例中,它将使用已填充“[0,1]”的前两个值 - 这些是前两个斐波那契数。

第二个参数是将应用记忆的函数。在本例中是递归斐波那契函数:

function (shell, n) {
返回外壳(n - 1)+外壳(n - 2);

结果是序列中前两个数字的总和。

存储器首先检查它是否已经有缓存的结果。如果确实如此,它会立即返回。如果不是,则计算结果并将其存储在缓存中。如果不这样做,它就会一次又一次地重复,并且一旦达到序列中更高的数字,速度就会变得非常慢。

As the comments to your question suggest, you should walk through the code in a debugger to get a good understanding of what's going if you can't follow the explanation in the book. But I'll give you a brief overview of what's happening:

What's being demonstrated is 'memoisation' which is a common optimisation technique used in functional programming. A function is said to be pure if the result depends only on the arguments passed into it. So, if a function is pure you can cache the result based on the arguments - this technique is called memoisation. You would do this if a function is expensive to calculate and is called multiple times.

The classical example used to demonstrate this (as here) is generating Fibonacci numbers. I'm not going to go through how those are worked out, but basically as you go to higher and higher numbers you repeat yourself more and more as each number is calculated from the preceeding two numbers. By memoising each intermediate result you only have to calculate them once hence making the algorithm much faster (much, much faster as you go higher up the sequence).

As far as this code is concerned the memoizer takes two parameters - 'memo' which is the cache. In this case it's going in with the first two values already filled in the '[0,1]' - these are the first two Fibonacci numbers.

The second parameter is the function to which the memoisation will be applied. In this case a recursive Fibonacci function:

function (shell, n) {
return shell(n - 1) + shell(n - 2);
}

i.e. the result is the sum of the previous two numbers in the sequence.

The memoizer first of checks to see if it already has a cached result. If it does it returns that immediately. If not it calculates the result and stores it in the cache. Without doing this it'd be repeating itself again and again and rapidly gets impossibly slow once to get to the higher numbers in the sequence.

清风疏影 2024-10-02 10:37:56

要评估该函数,您只需调用它:

fibonacci(15);

如果您想查看结果,最简单的方法是:

alert(fibonacci(15));

如果您想更频繁地执行此操作,请下载 Firebug,并在脚本底部执行此操作:

Console.log(fibonacci(15));

或者直接在 Firebug 控制台中键入此内容,然后按回车键:

fibonacci(15)

To evaluate the function, you simply need to call it:

fibonacci(15);

If you want to see the result, the simplest way would be:

alert(fibonacci(15));

If you want to do this more often, then download Firebug, and do this at the bottom of your script:

Console.log(fibonacci(15));

Or type this directly into the Firebug console, and then press return:

fibonacci(15)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文