수색…
통사론
- 화살표 함수와 같이 암묵적으로 또는 명시 적으로 return call () 만 호출하면 꼬리 호출 구문이 될 수 있습니다
- function foo () {return bar (); } // 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; // bar는 + 1을 반환하기 위해 컨텍스트가 필요하므로 꼬리 호출이 아닙니다.
비고
TCO는 ES2015 사양에서 언급했듯이 PTC (Proper Tail Call)라고도합니다.
Tail (Tail Call Optimization)이란 무엇입니까?
TCO는 엄격 모드 에서만 사용할 수 있습니다.
모든 언어 기능 지원을 위해 브라우저 및 자바 구현을 항상 확인하고 자바 스크립트 기능이나 구문과 마찬가지로 향후 변경 될 수 있습니다.
전역 프레임 스택에 함수 상태를 푸시 할 필요가 없으며 초기 호출 함수로 직접 복귀하여 각 호출 함수를 단계적으로 수행 할 필요가 없으므로 재귀 및 중첩 된 함수 호출을 최적화하는 방법을 제공합니다.
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()
의 끝 부분에 있으므로 프레임 스택에 a()
의 상태를 푸시 할 필요가 없음을 인식합니다. 경우 b(0)
보다는 복귀보다 반환 a()
이 글로벌 프레임에 바로 리턴한다. 중간 단계를 제거하여 추가 최적화.
TCO는 재귀 호출이 발생할 때마다 프레임 스택이 커지지 않기 때문에 재귀 함수가 무한 재귀를 허용합니다. TCO가없는 재귀 함수는 제한된 재귀 깊이를가집니다.
참고 TCO는 자바 스크립트 엔진 구현 기능으로 브라우저가 지원하지 않으면 transpiler를 통해 구현할 수 없습니다. TCO를 구현하는 데 필요한 추가 구문은 없으므로 TCO가 웹을 손상시킬 수 있다는 우려가 있습니다. 세계로 출시되는 것은 신중하며 브라우저 / 엔진 특정 플래그가 인식 가능한 미래를 위해 설정되어야 할 수도 있습니다.
재귀 루프
Tail Call Optimization은 호출 스택 오버 플로우 나 증가하는 프레임 스택의 오버 헤드에 대한 염려없이 재귀 루프를 안전하게 구현할 수있게합니다.
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