摘要:被你忽略的尾調用尾調用是什么在有一個新特性尾調用用最簡單的一句話描述就是某個函數的最后一步再調用另一個函數,聽起來挺簡單的,但是它的功能特別強大,直接給你擼個例子吧。如果函數內部還調用函數,那就還有一個的調用記錄棧,以此類推。
title: 被你忽略的‘尾調用’
date: 2017-05-02 16:52:22
在ES6有一個新特性:尾調用
用最簡單的一句話描述就是‘某個函數的最后一步再調用另一個函數’,聽起來挺簡單的,
但是它的功能特別強大,直接給你擼個例子吧。
function a(x) { return b(x); }
這個函數的最后一步再調用另一個函數,這就是尾調用。
以下幾點不屬于尾調用
在調用函數b之后還存在賦值的操作
function a(x) { let m = b(x); return m; }
返回的那個函數沒有加return
function a(x) { b(x); }
在調用之后還存在其他的賦值操作
function a(x) { return b(x) - 2; }尾調用優化
函數調用會在內存形成一個"調用記錄",又稱"調用幀"(call frame),保存調用位置
和內部變量等信息。如果在函數A的內部調用函數B,那么在A的調用記錄上方,還會形成
一個B的調用記錄。等到B運行結束,將結果返回到A,B的調用記錄才會消失。如果函數B
內部還調用函數C,那就還有一個C的調用記錄棧,以此類推。所有的調用記錄,就形成一個
"調用棧"
來個例子吧
function a() { let p = 2; let q = 3; return b(p + q) } a();
仔細觀察上面的代碼就會發現啊a函數似乎是多余的吧,因為b函數是尾調用函數,執行到
這里函數a早就結束了,完全可以刪除a函數了只保留b的調用幀即可。
尾調用優化:就是只保留內層函數的調用幀,如果所有函數都是尾調用,那么完全可以
做到每次執行時調用幀只能有一項,將大大節省內存,也就是尾調用的意義所在了。
注意的一點就是內層函數運用了外層函數的變量便不能進行尾調用優化了。記住哦!
顧名思義,在一個尾調用中,如果函數最后的尾調用位置上是這個函數本身,則被稱為尾遞
歸。遞歸很常用,但如果沒寫好的話也會非常消耗內存,導致爆棧。但是對于尾遞歸來說只
存在一個調用棧,便永遠不會發生“棧溢出”錯誤。
就以求一個給出數的階乘來探索吧。在傳統的做法中利用n的遞減乘上原函數,這樣復雜度
便會很高,數據量一大便會發生“棧溢出”的錯誤了。
傳統的解決辦法
function f(n) { if(n === 1) { return 1; } return n * f(n -1); }
尾調用
function a(n, t) { if(n === 1) { return t; } return a(n - 1, n * t) }
對比兩個解決辦法的復雜度就知道,尾調用只保留了一個記錄。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91720.html
摘要:是捕捉異常的神器,不管是調試還是防止軟件崩潰,都離不開它。今天筆者介紹一下加上后的執行順序嗯按順序執行了。現在筆者在語句塊中故意報錯看來,和的都需要先經過。 try-catch是捕捉異常的神器,不管是調試還是防止軟件崩潰,都離不開它。今天筆者介紹一下加上finally后的執行順序 function test() { try { console.log(1); } fin...
摘要:是捕捉異常的神器,不管是調試還是防止軟件崩潰,都離不開它。今天筆者介紹一下加上后的執行順序嗯按順序執行了。現在筆者在語句塊中故意報錯看來,和的都需要先經過。 try-catch是捕捉異常的神器,不管是調試還是防止軟件崩潰,都離不開它。今天筆者介紹一下加上finally后的執行順序 function test() { try { console.log(1); } fin...
摘要:每個函數調用都將開辟出一小塊稱為堆棧幀的內存。當第二個函數開始執行,堆棧幀增加到個。當這個函數調用結束后,它的幀會從堆棧中退出。保持堆棧幀跟蹤函數調用的狀態,并將其分派給下一個遞歸調用迭。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著滬江血液的純粹工程:認真,是 HTM...
摘要:根據該規則,返回第個斐波那契數。尾遞歸函數調用自身,稱為遞歸。一個前端眼中的斐波那契數列解斐波那契數列的實用解法調用棧尾遞歸和手動優化尾調用優化譯我從用寫斐波那契生成器中學到的令人驚訝的件事 斐波那契數列是以下一系列數字: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, ... 在種子數字 0 和 1 ...
摘要:如果所有函數都是尾調用,那么完全可以做到每次執行時,調用幀只有一項,這將大大節省內存。等同于等同于注意,只有不再用到外層函數的內部變量,內層函數的調用幀才會取代外層函數的調用幀,否則就無法進行尾調用優化。 showImg(https://segmentfault.com/img/bVbrTHp?w=1080&h=1920); 1. 函數參數的默認值 1.1 用法 在ES6之前是不能為...
閱讀 2100·2021-11-11 16:55
閱讀 3171·2021-10-11 10:58
閱讀 3038·2021-09-13 10:28
閱讀 3967·2021-07-26 23:57
閱讀 1005·2019-08-30 15:56
閱讀 1331·2019-08-29 13:15
閱讀 1258·2019-08-26 18:18
閱讀 1266·2019-08-26 13:44