ここから本文です

javascriptの再帰関数で狙った結果が返ってこない。具体的には、 再帰関数内でif ...

xuh********さん

2016/12/1823:30:27

javascriptの再帰関数で狙った結果が返ってこない。具体的には、
再帰関数内でif elseで判定を行いelseだった場合returnで値を返そうとするとundefinedとなってしまいます。

----------------------------------------------
function tes(x){
var cnt = x
cnt++
if(cnt < 5){
tes(cnt) //再帰
}else{
return 1;
}
}
console.log(tes(0)) // undefined
------------------------------------------------
if else から外してreturnで返すとちゃんと値が返ってきます。
再帰関数ではない関数の場合もif elseで狙ったreturnが返ってきました。
------------------------------------------------
function tes(x){
var cnt = x
cnt++
if(cnt < 5){
tes(cnt) //再帰
} // elseなし
return 1;
}
console.log(tes(0)) // 1
------------------------------------------------

これはどういう仕様なのでしょうか?
javascript初級や中級の参考サイトを見て勉強した程度の知識しかないので参考になるようなサイトもあればお願いします。

閲覧数:
212
回答数:
2
お礼:
100枚

違反報告

ベストアンサーに選ばれた回答

プロフィール画像

カテゴリマスター

sii********さん

2016/12/1900:05:30

最初にtesが実行されるとき、

> tes(cnt) //再帰

ここに流れて再帰がかかるわけですが、再帰というのはその処理が終わったとき、元の場所に戻ってきます。つまり、その続きの処理が実行されます。

しかし、前者のソースではifの分岐でこの再帰に流れた場合、後続の処理が1つも存在しません。そのため、undefinedがreturnされるという、関数としてのデフォルトの処理が行われます。

後者のソースでは、再帰に流れようが流れまいが最後に1をreturnしていますので、再帰のループが終わった後、console.logに1が渡されます。

------------

前者のソースだと5回、tesが実行されますので、実行順に(1)~(5)と呼びます。

console.log が (1) を呼び出す (x=0)

cnt=1: (1) が (2) を呼び出す (x=1)

cnt=2: (2) が (3) を呼び出す (x=2)

cnt=3: (3) が (4) を呼び出す (x=3)

cnt=4: (4) が (5) を呼び出す (x=4)

cnt=5: (5) が (4) に1をreturnする

(4) が (3) にundefinedをreturnする

(3) が (2) にundefinedをreturnする

(2) が (1) にundefinedをreturnする

(1) が console.log にundefinedをreturnする

  • 質問者

    xuh********さん

    2016/12/1912:24:10

    BAメッセージ超過のためここに書かせて頂きます。

    rebouno999さん sii_sideさん
    お二人とも丁寧な解説をして頂きありがとうございました!
    両方の回答を合わせたものが私の基礎的な理解の間違いを導き出してくれました。

    再帰させた後はその関数がreturnと同じように打ち切られると思っていました。
    tes(1)の場合、if(cnt <5){}でtes(2)を実行させ、tes(1)はそこで打ち切り残りの処理は何もしないと。
    ...
    tes(cnt)
    console.log("a")
    }else{

    この場合tes(1)はconsole.log("a")を切り捨てるようなイメージを持っていました。


    ------------------------------
    if(cnt < 5){
    return tes(cnt); //再帰
    }else{
    return 1;
    }
    ------------------------------
    returnで再帰させ処理の打ち切りと戻り値を付けるようにしました。

返信を取り消しますが
よろしいですか?

  • 取り消す
  • キャンセル

質問した人からのコメント

2016/12/19 12:25:55

お二人とも丁寧な説明をありがとうございました!
私の基礎的な間違いが分かり理解が深まりました。

ベストアンサー以外の回答

1〜1件/1件中

reb********さん

2016/12/1823:59:58

tes(0) が呼ばれ、
tes(1) が呼ばれ、
tes(2) が呼ばれ、
tes(3) が呼ばれ、
tes(4) が呼ばれ、tes(4)は1を返しますが、
tes(4)が1を返したその戻り値を、tes(3)で呼んだ元では見ていないです。

引数が3のときの挙動は以下のようなイメージで、①~⑤の部分を動きます。

function tes(3) {
ㅤvar cnt = 3; // ①
ㅤcnt++; // ② cntは4に
ㅤif(cnt < 5){ // ③ 5未満なのでifの中に
ㅤㅤtes(4); // ④ この戻り値は 1 だが戻り値を捨てている!
ㅤ} else {
ㅤㅤ・・・
ㅤ}
}// ⑤ returnで何かを返すことなく終了

戻り値を返さない関数の戻り値を評価したのでundefinedになっているわけですね。
tes(cnt) ではなく return tes(cnt); とすると、最後まで 1 が返されますよ。

この質問につけられたタグ

みんなで作る知恵袋 悩みや疑問、なんでも気軽にきいちゃおう!

Q&Aをキーワードで検索:

Yahoo! JAPANは、回答に記載された内容の信ぴょう性、正確性を保証しておりません。
お客様自身の責任と判断で、ご利用ください。
本文はここまでです このページの先頭へ

「追加する」ボタンを押してください。

閉じる

※知恵コレクションに追加された質問は選択されたID/ニックネームのMy知恵袋で確認できます。

不適切な投稿でないことを報告しました。

閉じる