溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

web中如何優化尾調用

發布時間:2022-03-01 10:56:34 來源:億速云 閱讀:184 作者:小新 欄目:開發技術

這篇文章主要為大家展示了“web中如何優化尾調用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“web中如何優化尾調用”這篇文章吧。


尾調用

從字面理解,自然而言就是在函數的尾部返回一個函數的調用,通常來說,指的是函數執行的最后一步。

舉個例子

const fn = () => f1() || f2()
// 這里的話, f2函數有可能是尾調用,f1不可能是尾調用

為什么f1函數不是呢,我們看這個函數的等價形式

const fn = function () {
    const flag = f1()
    if(flag) {
        return flag
    } else {
        return f2()
    }
}

似乎寫到這里,根據尾調用定義,我們就明白了,只有f2函數是在尾部調用。

說到這里,為什么要說尾調用呢?我們事先想一想傳統的遞歸,典型的就是首先執行遞歸調用,然后根據這個遞歸的返回值并結算結果,那么傳統的遞歸缺點有哪些呢

  • 效率低,占內存。

  • 如果遞歸鏈過長,可能會stack overflow

那么我們是不是可以做優化呢,這就可以涉及上面提到的尾調用,它的原理是啥呢

按照阮一峰老師在es6的函數擴展中的解釋就是:函數調用會在內存形成一個“調用記錄”,又稱“調用幀”(call frame),保存調用位置和內部變量等信息。如果在函數A的內部調用函數B,那么在A的調用幀上方,還會形成一個B的調用幀。等到B運行結束,將結果返回到A,B的調用幀才會消失。如果函數B內部還調用函數C,那就還有一個C的調用幀,以此類推。所有的調用幀,就形成一個“調用?!保╟all stack)。

這里的“調用幀”和“調用?!?,說的應該就是“執行環境”和“調用?!?。因為尾調用時函數的最后一部操作,所以不再需要保留外層的調用幀,而是直接取代外層的調用幀,所以可以起到一個優化的作用。

從上述的描述中,我們視乎可以理解成

  • 它的原理類似于當編譯器檢測到一個函數調用是尾遞歸時,它會覆蓋當前的活動記錄而不是在函數棧中創建一個新的調用記錄。

  • 這樣子,我們也可以理解成,不同的語言編譯器或者是解釋器做了尾遞歸優化,才讓它不會爆棧。

既然是這樣子的話,尾遞歸的優化,取決于瀏覽器,那具體有哪些主流瀏覽器支持呢

safari 和火狐,有興趣的可以去了解一下,可以寫個斐波那契數列數列驗證一下。

手動優化

既然我們知道了,很多瀏覽器對于尾遞歸的優化支持的瀏覽器并不多,那你會好奇,當我們使用尾遞歸進行優化的時候,依然出現棧溢出的錯誤,那么我們如何解決呢?

我在網上看到一個不錯的方案,采用的是蹦床函數

function trampoline(f) {
  while (f && f instanceof Function) {
    f = f();
  }
  return f;
}

那么如何使用呢

我們拿最常見的斐波那契數列來說吧

function fibonacci(n) {
  if (n === 0) return 0
  if (n === 1) return 1
  return fibonacci(n - 1) + fibonacci(n - 2)
}

根據上面的式子,我們可以將其寫成迭代形式,用一個變量去緩存它的值

function fibonacci (n, ac1 = 0, ac2 = 1) {
    return n

以上是“web中如何優化尾調用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

web
AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女