繁体   English   中英

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

[英]How do i apply TCO(Tail Call Optimiztion) on recursive anonymous Function in ES5

如果我可以 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. 尾调用的结果作为函数值返回。

也许最难避免的情况是使用闭包。 因为闭包可以访问包含范围内的变量,所以可能会关闭尾调用优化。 例如:

"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。

暂无
暂无

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

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