サーチ…
構文
- 矢印関数のように暗黙的に呼び出すか、明示的に呼び出すかのどちらかを返すだけで、末尾呼び出し文
- 関数foo(){リターンバー(); } // barの呼び出しは末尾呼び出しです
- 関数foo(){bar(); } // barはテールコールではありません。戻り値が与えられていない場合、この関数はundefinedを返します。
- const foo =()=> bar(); // bar()はテールコールです
- const foo =()=>(poo()、bar()); // pooはテールコールではなく、barはテールコールです
- const foo =()=> poo()&& bar(); // pooはテールコールではなく、barはテールコールです
- const foo =()=> bar()+ 1; //バーは+ 1を返すためにコンテキストを必要とするため、テールコールではありません
備考
TCOは、ES2015仕様で言及されているように、PTC(Proper Tail Call)としても知られています。
Tail Call Optimization(TCO)とは何ですか?
いつものように、ブラウザやJavaScriptの実装をチェックして言語機能をサポートしています.JavaScriptの機能や構文も今後変更される可能性があります。
ファンクション状態をグローバルフレームスタックにプッシュする必要性を排除し、最初の呼び出し関数に直接戻って各呼び出し関数をステップダウンする必要をなくすことで、再帰的および深くネストされた関数呼び出しを最適化する方法を提供します。
function a(){
return b(); // 2
}
function b(){
return 1; // 3
}
a(); // 1
TCOがなければa()
を呼び出すとその関数の新しいフレームが作成されます。その関数が呼び出したときb()
a()
のフレームは、フレームスタックにプッシュされ、新しいフレームが機能のために作成されたb()
場合b()
への復帰a()
のフレームは、フレームスタックからポップされます。これはすぐにグローバルフレームに戻り、スタック上に保存されている状態は一切使用しません。 a()
TCOは、 a()
からb()
a()
への呼び出しが関数a()
末尾にあることを認識し、 b()
の状態をフレームスタックにプッシュa()
必要はありません。場合b(0)
というに戻るより返すa()
はグローバルフレームに直接戻ります。中間ステップを排除してさらに最適化する。
TCOを使用すると、再帰呼び出しごとにフレームスタックが大きくならないため、再帰関数には無期限の再帰を持たせることができます。 TCO再帰関数を使用しない場合、再帰的な深さは限られています。
注意 TCOはJavaScriptエンジンの実装機能です。ブラウザがサポートしていない場合は、それをtranspiler経由で実装することはできません。 TCOを実装するために必要な仕様には構文がありません。したがって、TCOがWebを破壊する可能性があります。世界へのリリースは慎重であり、ブラウザー/エンジン固有のフラグを知覚可能な将来に設定する必要があるかもしれません。
再帰的ループ
テールコールの最適化により、呼び出しスタックのオーバーフローや、増大するフレームスタックのオーバーヘッドを気にせずに、再帰的なループを安全に実装することができます。
function indexOf(array, predicate, i = 0) {
if (0 <= i && i < array.length) {
if (predicate(array[i])) { return i; }
return indexOf(array, predicate, i + 1); // the tail call
}
}
indexOf([1,2,3,4,5,6,7], x => x === 5); // returns index of 5 which is 4