この記事の内容は、再帰とは何ですか? JavaScript の再帰についての詳細な説明は、参考になると思います。
1. 再帰とは何ですか?
再帰の概念は非常に単純で、「自分自身を呼び出す」です (以下の例として関数を取り上げます)。
再帰を分析する前に、JavaScript の「コールスタック」の概念を理解する必要があります。
2. スタックのプッシュとポップ
スタックとは何ですか?メモリ内の特定の領域を箱に例えると、この領域がスタックをプッシュすることになります。したがって、最初に置くものは箱の底に置き、最後に置くものは箱の上部に置きます。ボックスから何かを取り出すことは、*スタックからそれを押し出すこととして理解できます。
つまり、私たちは物事を上から下へ運ぶ習慣があるという結論に達しました。最初に置くものは箱の底で、最後に手に入れるものです。
JavaScript では、関数が呼び出されたときにスタック プッシュが発生します。Pop は、return キーワードを含む文が見つかった場合、または実行が終了した場合にのみ発生します。
例を見てみましょう。このコードの実行順序は何でしょうか?
function fn1() { return 'this is fn1' } function fn2() { fn3() return 'this is fn2' } function fn3() { let arr = ['apple', 'banana', 'orange'] return arr.length } function fn() { fn1() fn2() console.log('All fn are done') } fn()
一連のスタックのプッシュとポップの動作が上記で発生しました:
1. まず、最初はスタック (ボックス) が空です
2 関数 fn が実行されます。 、fn が最初にスタックにプッシュされ、スタックの一番下に配置されます (ボックス)
3。関数 fn 内では、関数 fn1 が最初に実行され、fn1 が fn
# の上のスタックにプッシュされます。 ##4. 関数 fn1 が実行され、return キーワードに移動すると、これが fn1 になり、fn1 がスタックからポップされ、ボックス内には fn5 だけが残ります。 fn の場合、fn1 が実行された後、関数 fn2 の実行が開始され、fn2 がスタックにプッシュされますが、fn2 の内側で fn3 が検出されると、fn3 の実行が開始されるため、fn3 がスタックにプッシュされます6. このとき、スタック内での順序は、 fn3 7。キーワードが関数 fn3 内で検出され、fn3 は実行後にスタックから飛び出し、関数 fn2 に戻ります。fn2 も return キーワードに遭遇し、スタックから飛び出し続けます。 8. スタックには fn だけが存在します。console.log('All fn arened') ステートメントを実行すると、fn がスタックから飛び出します。 9. これでスタックは再び空になりました。 上記の手順は人々を混乱させやすいので、フローチャートを次に示します: Chrome ブラウザ環境での実行を見てみましょう:
#3. 再帰##最初に単純なものを見てみましょう。 JavaScript 再帰
function sumRange(num) { if (num === 1) return 1; return num + sumRange(num - 1) } sumRange(3) // 6
上記のコード実行シーケンス:
1. 関数 sumRange(3) が実行され、sumRange(3) がスタックにプッシュされ、return キーワードが検出されますが、 SumRange(num - 1) の呼び出しは sumRange(2)
2 であるため、スタックからすぐに取り出すことはできません。したがって、sumRange(2) はスタックにプッシュされ、以下同様に sumRange(1) がプッシュされます。最後に、sumRange(1) はスタックをポップして 1 を返し、sumRange(2) はスタックをポップして 2 を返し、sumRange(3) はスタックをポップします
4、つまり 3 2 1 の結果は 6
フローチャートを見てください
つまり、再帰これは、スタックをプッシュおよびポップするプロセスでもあります。
再帰は非再帰として表現できます。以下は、上記の再帰の例と同等の実行です。// for 循环
function multiple(num) {
let total = 1;
for (let i = num; i > 1; i--) {
total *= i
}
return total
}
multiple(3)
上記の場合、次のように例を変更します。
function multiple(num) { if (num === 1) console.log(1) return num * multiple(num - 1) } multiple(3) // Error: Maximum call stack size exceeded
上記のコードの最初の行に return キーワード文がないため、再帰の終了条件がないため、常にプッシュされます。スタックが発生し、メモリ リークが発生します。
再帰が起こりやすいエラー ポイント終了ポイントが設定されていません
以下は練習問題です。
1. 文字列を受け入れて文字列を返す関数を作成します。この文字列は元の文字列を反転したものです。
2. 文字列を受け取り、前から後ろまで 1 文字を比較する関数を作成します。2 つの文字が等しい場合は true を返し、等しくない場合は false を返します。 3. 配列を受け取り、フラット化された新しい配列を返す関数を作成します。
4. オブジェクトの値が偶数の場合、それらを加算して合計値を返す関数を作成します。
5. オブジェクトを受け取り、配列を返す関数を作成します。この配列には、オブジェクト内の文字列であるすべての値が含まれます。
7.参考1
function reverse(str) { if(str.length 参考2<p></p><pre class="brush:php;toolbar:false">function isPalindrome(str){ if(str.length === 1) return true; if(str.length === 2) return str[0] === str[1]; if(str[0] === str.slice(-1)) return isPalindrome(str.slice(1,-1)) return false; } var str = 'abba' isPalindrome(str)
function flatten (oldArr) { var newArr = [] for(var i = 0; i 参考4<p></p><pre class="brush:php;toolbar:false">function nestedEvenSum(obj, sum=0) { for (var key in obj) { if (typeof obj[key] === 'object'){ sum += nestedEvenSum(obj[key]); } else if (typeof obj[key] === 'number' && obj[key] % 2 === 0){ sum += obj[key]; } } return sum; } nestedEvenSum({c: 4,d: {a: 2, b:3}})
function collectStrings(obj) { let newArr = [] for (let key in obj) { if (typeof obj[key] === 'string') { newArr.push(obj[key]) } else if(typeof obj[key] === 'object' && !Array.isArray(obj[key])) { newArr = newArr.concat(collectStrings(obj[key])) } } return newArr } var obj = { a: '1', b: { c: 2, d: 'dd' } } collectStrings(obj)
5 。 まとめ######
再帰の本質は、再帰部分を検討するときに、多くの場合、最初に通常の部分について考える必要があるということです。JavaScript 再帰でよく使用されるメソッドは次のとおりです。
配列: スライス、連結
String : スライス、substr、substring
オブジェクト: Object.assign
以上が再帰とは何ですか? JavaScriptの再帰の詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。