今天在開發中遇到一個遞歸方面的錯誤,修改了好多遍才發現自己對於遞歸返回上的認識錯誤。一共發現兩個問題,先說第一個,返回值的問題,上問題代碼
1 var value=[1,2,3,4,5,6]; 2 var result=[]; 3 var i; 4 function find(i){ 5 if(i<4){ 6 result[i]=value[i] 7 find(i+1); 8 } 9 else 10 return result; 11 } 12 find(0);
這段代碼返回為undefined,原因在於返回值沒有弄清楚,首先,我們調用的是find(0),而find(0)是沒有返回值的,注意那個return result並不是find(0)的返回值,那只是if語句條件不滿足之后的返回語句,在f(0)中我們並沒有進入else分支,你調用find(0),它繼續調用find(1),然后依此調用,然后條件不滿足了,語句結束,注意遞歸的find(4)並不會進入到else分支!!它只是使得if{}中不再調用!!!所以並沒有return!而在find(0)語句調用中我們同樣也沒有返回值,所以才會出現undefined的情況,同樣,我們可以這樣修改代碼:
1 var value=[1,2,3,4,5,6]; 2 var result=[]; 3 var i; 4 function find(i){ 5 if(i<4){ 6 result[i]=value[i] 7 find(i+1); return result; 8 } 9 else 10 return result; 11 } 12 find(0);
這樣在調用完了return,是find(0)沒有返回result,而我們需要的是find(4)的return result,所以我們在if{}中加一個return,返回的是調用完了result,遞推的return是最后一次調用的returnt,修改代碼為:
1 var value=[1,2,3,4,5,6]; 2 var result=[]; 3 var i; 4 function find(i){ 5 if(i<4){ 6 result[i]=value[i]; 7 return result; 8 find(i+1); 9 10 } 11 else 12 return result; 13 } 14 find(0);
這樣只返回1,因為只調用了一次就返回了,函數隨即停止,而上一種改法,要等所有的調用完成才返回。
我們可以再次修改,來佐證我們關於返回的看法:
1 var value=[1,2,3,4,5,6]; 2 var result=[]; 3 var i; 4 function find(i){ 5 if(i<4){ 6 result[i]=value[i]; 7 find(i+1); 8 9 } 10 else; 11 return result; 12 } 13 find(0);
我們看到,我們在else后面加了一個空語句,那這樣,find(0)就有返回了,返回調用完成之后的result值。
還有一個錯誤是,如果我們這樣來寫代碼:
var value=[1,2,3,4,5,6]; var result=[]; var i; function find(i){ if(i<4){ result[i]=value[i]; find(i+1); } else; return result[i]; } find(0);
我們發現也是返回undefined,這里我們誤解了一個很重要的一點,這里的i是參數而不是計數的i,它是形參賦值之后就沒有了,所以我們不能用result[i],那樣會恆返回result[0]而對於這樣兩個錯誤綜合起來的寫法
1 var value=[1,2,3,4,5,6]; 2 var result=[]; 3 var i; 4 function find(i){ 5 if(i<4){ 6 result[i]=value[i] 7 find(i+1); 8 } 9 else 10 return result[i]; 11 } 12 find(0);
則會返回undefined,因為首先if本身執行完了就是沒有返回值的,再者即便return 也只能return result[0]