javascript - 我如何在 ES5 中的递归匿名函数上应用 TO(尾调用优化)

标签 javascript node.js recursion ecmascript-6

如果我可以 tco 命名递归函数,那么应该有一种方法可以 tco 匿名递归函数。如果有办法,请在下面解释如何执行此操作,这是我的递归函数和 TCO 函数。

function recursive(length, callback) {

    tco((function (i, sum) {
        var args = arguments;
        if (i > length) {
            console.log("break statement");
            callback(sum)
            return sum
        } else {
            return args.callee(i + 1, sum + i)
        }
    }))(0, 0)
}

function tco(f) {
    var value;
    var active = false;
    var accumulated = [];

    return function accumulator() {
        accumulated.push(arguments);

        if (!active) {
            active = true;

            while (accumulated.length) {
                value = f.apply(this, accumulated.shift());
            }

            active = false;

            return value;
        }
    }
}

最佳答案

尾调用优化

ES6 提议对尾调用系统进行更改,这是一种引擎优化。尾调用是指一个函数作为另一个函数的最后一条语句被调用,如下所示:

function doSomething() {
    return doSomethingElse();   // tail call
}

ECMAScript 6 旨在减少严格模式下某些尾调用的调用堆栈大小。通过此优化,不会为尾调用创建新的堆栈帧,只要满足以下条件,就会清除并重新使用当前堆栈帧:

  1. 必须开启严格模式。
  2. 尾调用不需要访问当前堆栈帧中的变量(意味着该函数不是闭包)。
  3. 进行尾调用的函数在尾调用返回后没有进一步的工作要做。
  4. 尾调用的结果作为函数值返回。

Perhaps the hardest situation to avoid is in using closures. Because a closure has access to variables in the containing scope, tail call optimization may be turned off. For example:

"use strict";

function doSomething() {
    var num = 1,
        func = () => num;

    // not optimized - function is a closure
    return func();
}

利用 TCO 优化:

考虑这个计算阶乘的函数:

"use strict";
function factorial(n) {

    if (n <= 1) {
        return 1;
    } else {

        // not optimized - must multiply after returning
        return n * factorial(n - 1);
    }
}

为了优化函数,您需要确保乘法不会发生在最后一次函数调用之后。

"use strict";
function factorial(n, p = 1) {

    if (n <= 1) {
        return 1 * p;
    } else {
        let result = n * p;

        // optimized
        return factorial(n - 1, result);
    }
}

来源:Nicholas Zakas 的一本很棒书,Understanding ECMAScript 6。

关于javascript - 我如何在 ES5 中的递归匿名函数上应用 TO(尾调用优化),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39562817/

相关文章:

JavaScript,只能使用下划线 _ 访问属性

javascript - 设置ReactJS会导致额外的div,新组件?

javascript - 寻找快速传播内容的想法

javascript - 确定去优化的原因

node.js - 尝试在heroku中部署 Node 应用程序时不断收到应用程序错误

java - 很难理解递归

Java无限递归自引用类型

javascript - Firefox 中的渲染顺序

javascript - 使用 Redux Reselect 过滤评论

node.js - Express:查询文档是否存在