【问题标题】:Do the most current JavaScript/ECMAScripte compilers optimize out unnecessary variable assignment when returning the value from a function call?从函数调用返回值时,最新的 JavaScript/ECMAScript 编译器是否优化了不必要的变量赋值?
【发布时间】:2017-07-26 09:49:57
【问题描述】:

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

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

function create() {
    return doCreateAction();
}

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

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

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

【问题讨论】:

  • "分配给命名变量时,这段代码是否变慢了?"您是否尝试过自己做一些基准测试?题外话。我想说你最好重命名你的函数:) 为什么doCreateAction 返回的东西更好地描述为fileHandle?为什么不叫它createFileHandle 什么的。
  • 在这样一个显而易见的案例中?如果他们不这样做,我会非常惊讶。我知道是这样吗?不,我没有检查所有主要 JavaScript 引擎的优化器代码(更不用说它们的所有变体;例如,V8 目前同时使用解释器和编译器,直到最近它才使用两个编译器)。跨度>
  • 你想知道这个......为什么?
  • 如果您担心性能问题,您可能需要查看UglifyJSClosure Compilerprepack 或类似工具。但不要牺牲代码的可读性。并避免微优化,例如您的问题。
  • const create = doCreateAction; // returns file handle? :-)

标签: javascript performance optimization self-documenting-code


【解决方案1】:

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

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

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

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

因此,在这方面可能会产生影响,如果 TCO 是否以及何时被广泛实施,以及如果在这种情况下,实施会略微超出规范,显然是这样的情况,在效果,尾声。


我曾经对在那种情况下使用变量进行调试非常严格;然而,Chrome 的 devtools 的最新版本使得它不需要 目的(当然,无论如何,缩小器都会将其删除):如果您进入return,您会在变量的局部范围列表。当然,这仅在您使用 Chrome 的开发工具时才有用(例如,Firefox 的 [还没有?])。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 2019-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 2014-11-15
    相关资源
    最近更新 更多