使用遞歸函數必須要符合兩個條件: 1、 在每一次調用自己時,必須是(在某種意義上)更接近於解; 這句話怎麼理解? 大家家裡都有樓梯吧?比如從一樓走到二樓,那麼我們的起點是一樓,目的地是二樓,當你往上每走一個臺階是不是越接近二樓,也就是越接近目的地。 因此這句話可以這樣理解:函數每一次調用自己時... ...
遞歸函數:是指函數直接或間接調用函數本身,則稱該函數為遞歸函數。
這句話理解起來並不難,從概念上出發,給出以下的例子:
function foo(){ console.log("函數 foo 是遞歸函數。"); foo(); }
這個例子的 foo 函數就是一個遞歸函數。
當你把這個函數拿到瀏覽器上運行的時候,你會發現記憶體溢出了,為什麼呢?因為這個遞歸函數沒有停止處理或運算的出口,因此
這個遞歸函數就演變為一個死迴圈。
那如何使用遞歸呢?
使用遞歸函數必須要符合兩個條件:
1、 在每一次調用自己時,必須是(在某種意義上)更接近於解;
這句話怎麼理解?
大家家裡都有樓梯吧?比如從一樓走到二樓,那麼我們的起點是一樓,目的地是二樓,當你往上每走一個臺階是不是越接近二樓,也就是越接近目的地。
因此這句話可以這樣理解:函數每一次調用自己時,就越接近於我們期望它完成的任務的終點。
2、必須有一個終止處理或計算的出口。
這句話的意思是:必須要有一個標準的標誌,讓函數結束調用函數自身。
比如,怎麼知道你已經走到二樓了呢?當你看到有個門,門牌上寫著 2F 的,然後推開它跨過去,那麼你就到二樓了。
用遞歸輸出對象里包含的所有屬性值(包括對象里的子孫對象):
var obj = { a:{ name:"john", age:26, sex:"male", child:{ firstChild:"mak", laseChild:"loy" } }, b:{ name:"joe", age:28, sex:"female", child:{ firstChild:"bill", secondChild:"ruth", laseChild:"yoki" } } }; function getObjValue(obj){ for(var k in obj){ if(typeof obj[k] !== "object"){ console.log(obj[k]); //遞歸出口 }else{ getObjValue(obj[k]); //函數調用函數自身 } } }; getObjValue(obj); // 輸出結果: // name=john // age=26 // sex=male // firstChild=mak // laseChild=loy // name=joe // age=28 // sex=female // firstChild=bill // secondChild=ruth // laseChild=yoki
使用建議:在使用遞歸時,要註意對遞歸函數的參數類型的檢查,一定要保證有一個終止處理或計算的出口。否則很容易演變為死迴圈,從而造成記憶體溢出。