0

假设我们在一个实现文件处理的对象中。我想编写代码以便于阅读。

很难判断返回类型的代码示例,尤其是当有多个嵌套函数调用时:

function create() {
    return doCreateAction();
}

通过引入一个澄清变量,这个例子更具可读性:

function create() {
    var fileHandle = doCreateAction();
    return fileHandle;
}

理论上,第二个版本可以执行相同的操作,因为编译器必须暂时存储 doCreateAction() 的结果(可能在一些隐藏的、匿名的、短期的临时变量中)。分配给命名变量时,这段代码会变慢吗?

4

1 回答 1

2

我想说要么他们确实优化了变量,要么不值得打扰;而且无论哪种情况,您都有更大的鱼要炸。:-) 但是关于尾调用有一个有趣的方面。

但首先,就简单性能而言:根据经验,这个简单的综合测试表明函数的性能不会因是否存在变量而有所不同。另请注意,如果您使用合适的缩小器,缩小器可能会在 JavaScript 引擎进入之前为您删除该变量。

继续尾调用:你可能知道,从 ES2015 开始,在严格模式下,规范需要尾调用优化(TCO),这意味着当函数 A 返回调用函数 B 的结果时,而不是让 B 返回其结果到A,然后将其返回给调用者,A将控制权直接传递给B,然后将结果返回给调用者。这在几个方面更有效(避免在堆栈上创建另一个帧,避免跳转)。

现在,这可能无关紧要,因为 JavaScript 引擎中 TCO 的开发即使没有死也至少会停滞不前。V8 团队开发了一个早期版本但放弃了它,SpiderMonkey 也没有;据我所知,只有 Safari 中的 JavaScriptCore 具有 TCO。但是,如果我正确阅读了规范(绝非易事),您的第一个示例doCreateAction位于尾部位置,因此可以通过 TCO 进行优化,但您的第二个示例没有。

因此,在这方面可能会产生影响,如果 TCO 是否以及何时被广泛实施,以及在这种情况下,实施是否略微超出规范,在这种情况下,显然它实际上是一个尾调用。


我曾经非常严格地在那种情况下使用变量进行调试。然而,Chrome 的 devtools 的最新版本使得它不必为此目的(当然,无论如何,缩小器都会将其删除):如果您进入 a return,您会在本地范围的变量列表中看到返回值。当然,这仅在您使用 Chrome 的 devtools 时才有用(例如,Firefox 的 [还没有?])。

于 2017-07-26T11:36:33.877 回答