簡體   English   中英

JavaScript 尾調用中的函數是否經過優化?

[英]Are functions in JavaScript tail-call optimized?

我一直在嘗試了解 JavaScript 上下文中的Tail call optimization ,並為factorial()編寫了以下遞歸和尾遞歸方法。

遞歸:

function factorial (n) {
  if (n < 2) {
    return 1;
  } else {
    return n * factorial(n-1);
  }
}

尾遞歸:

function factorial (n) {
  function fact(n, acc) {
    if (n < 2) {
      return acc;
    } else {
      return fact(n-1, n * acc);
    }
  }

  return fact(n, 1)
}

但我不確定該函數的tail-recursive版本是否會像在其他語言(如 Scala 等)中一樣由 JavaScript 編譯器優化。有人可以幫我解決這個問題嗎?

更新:截至 2020 年 1 月 1 日,Safari 是唯一支持尾調用優化的瀏覽器。

Chromium 團隊明確指出,Tail Call Optimization 未在積極開發中,可以在此處進行跟蹤。

可以在此處跟蹤 Firefox 的實現

原帖

是的,ES2015 在嚴格模式下提供尾調用優化。 Axel Rauschmayer 博士在下面的鏈接中對其進行了精美的闡述,因此我不會在這里重復他的話。

注意:ES 5 沒有優化尾調用。

http://www.2ality.com/2015/06/tail-call-optimization.html

理論上是的。 正如另一個答案所述。

但實際上,截至 2017 年 7 月,否。只有 Safari 支持它。

Javascript ES6 (ES2015) 兼容性: https ://kangax.github.io/compat-table/es6/

正如其他答案所說,實際上並非如此。 但是,您可以定義一個實用程序來提供幫助。

class Tco {
  constructor(func) {
    this.func = func;
  }
  execute() {
    let value = this;
    while (value instanceof Tco)
      value = value.func();
    return value;
  }
}

const tco = (f) => new Tco(f);
function factorial (n) {
  const fact = (n, acc) => tco(() => {
    if (n < 2) {
      return acc;
    } else {
      return fact(n-1, n * acc);
    }
  });

  return fact(n, 1).execute();
}

console.log(factorial(2000000)); // Infinity

如您所見,這允許您編寫僅在語法上有很小差異的尾遞歸函數,而不會遇到最大調用堆棧錯誤。

Safari 是唯一支持尾調用優化的瀏覽器。 ES2015 在嚴格模式下提供尾調用優化

    function factorial(n, returnVal= 1) {
      'use strict';
       if (n <= 1) return returnVal;
        return factorial(n - 1, n * returnVal);
}


factorial(555)

按照鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM