BabelJS如何实现尾递归?

时间:2015-05-21 08:54:18

标签: javascript tail-recursion babeljs

Babel如何实现尾递归?

transpiled es5 code如何运作?

1 个答案:

答案 0 :(得分:6)

我认为我会发布一个详细的解释,允许那些从谷歌登陆的人希望能够更快地加快理解。

请注意,以下解释源于我从代码中可以看出的内容(没有与Babel的作者或其代码中的其他专家进行过协商),因此我所知道的含义是否与@sebmck或其他为这次转型做出贡献的人。

"use strict"; // ES2015/ES6 modules are assumed to be in strict mode.

function factorial(_x2) {
    // This variable is the list of arguments to factorial.
    // Since factorial may be called again from within this function
    // (but must be called indirectly to prevent call stack growth),
    // a custom arguments-like variable must be maintained.
    var _arguments = arguments;

    // _again equals true when the original factorial function should be called
    // once more.
    var _again = true;

    // This line creates a labeled while loop, use to allow continuing this
    // specific loop, without the requirement of having no nested while loops
    // Nested while loops would cause a "continue" statement within them to
    // execute them, not this loop.
    _function: while (_again) {

        // The variable used in the original factorial function was called "n",
        // this method allows Babel to not rename it, but simply assign the
        // possibly modified first argument of the factorial function to it.
        var n = _x2;

        // Temporal dead zone (TDZ) mechanic
        acc = undefined;

        // The "use strict" directive from the original function
        "use strict";

        // Beginning of user code, this is always inserted to ensure that if
        // this is the final run, the while loop will not run again.
        _again = false;

        // This is Babel's default argument handling. The steps, in order, are:
        // 1. Make sure that there will not be an out-of-bounds access for the
        //    undefined check.
        // 2. Check if the second argument to the current iteration is undefined,
        //    if yes: the default value is `1`, if no, use the value of the first argument.
        var acc = _arguments.length <= 1 || _arguments[1] === undefined ? 1 : _arguments[1];

        // Input code - no modifications.
        if (n <= 1) return acc;

        // The following three lines are the call to factorial() within factorial
        // in the input code. The first line assigns the new arguments, as well
        // as updating the _x2 variable to it's new value. The second line
        // overrides the assignment in the beginning of the loop.
        // The third line brings the loop back to the beginning.
        _arguments = [_x2 = n - 1, n * acc];
        _again = true;
        continue _function;
    }
}