ES6 마지막 호출 최적화 사용 정보
뭐 공부 해요?
예를 들어, 다음은 비귀속 끝 호출입니다.
function foo(x) {
return x
}
//
function bar(y) {
return foo(y + 1)
}
//
function baz() {
return 1 + bar(40)
}
baz() // 42
설명:foo(y+1)는bar(...)foo(...)완료되면 bar (...)완성했습니다. 그리고foo(...)로 돌아가기만 하면 됩니다.호출된 결과.그러나bar(40)는 꼬리 호출이 아닙니다. 완성된 후에baz()에서 결과를 되돌릴 수 있도록 1을 추가해야 하기 때문입니다.JavaScript에서 새 함수를 호출하려면 호출 창고를 관리하기 위해 미리 남겨진 내용을 추가해야 합니다.그래서 앞의 코드는 보통baz(),bar(...),foo(...) 스택 프레임을 유지합니다.
그러나 TCO를 지원하는 엔진이 foo(y+1) 호출이 끝에 있음을 인식하면 bar(...)기본적으로 완성되었습니다. 그러면 foo(...)를 호출합니다.새 프레임 창고를 만들 필요가 없고, 기존 bar (...) 를 다시 사용할 수 있습니다.프레임 스택입니다.이렇게 하면 속도가 빠를 뿐만 아니라 메모리도 절약할 수 있다.
무엇이 귀착이냐
컴퓨터 과학에서 꼬리 호출은 하나의 함수 안의 마지막 동작이 하나의 함수 호출 상황을 가리킨다. 즉, 이 호출의 반환 값이 현재 함수에 의해 직접 되돌아오는 상황을 가리킨다.이런 상황에서 이 호출 위치를 끝자리라고 한다.만약에 이 함수가 꼬리 위치에서 그 자체(또는 하나의 꼬리 호출 자체의 다른 함수 등)를 호출한다면 이런 상황을 꼬리 귀속이라고 하는 것은 귀속의 특수한 상황이다.꼬리 호출이 반드시 귀속 호출은 아니지만 꼬리 귀속은 특히 유용하고 실현하기 쉽다.
TCO의 의미
프로그램이 실행될 때 컴퓨터는 응용 프로그램에 일정한 메모리 공간을 분배한다.응용 프로그램은 자체적으로 얻은 메모리 공간을 분배하는데, 그 중 일부는 프로그램에서 호출되고 있는 각 함수의 운행 상황을 기록하는 데 사용된다. 이것이 바로 함수의 호출 창고이다.일반적인 함수 호출은 항상 호출 창고 맨 위에 새 창고 프레임 (stack frame, "스택 프레임"또는 약칭 "프레임") 을 추가합니다. 이 과정은 "스택"또는 "스택"(즉 새 프레임을 창고 꼭대기에 누르는 것) 이라고 합니다.함수의 호출 층수가 매우 많을 때, 호출 창고는 적지 않은 메모리를 소모하고, 심지어는 메모리 공간(창고 넘침)을 폭발시켜 프로그램이 심각하게 끊기거나 의외로 붕괴될 수도 있다.마지막 호출 창고는 특히 최적화되기 쉬워 메모리 공간의 사용을 줄일 수 있고 운행 속도도 높일 수 있다.그 중에서 꼬리 귀속 상황에 대한 최적화 효과가 가장 뚜렷하고 특히 귀속 알고리즘이 매우 복잡한 상황이다.
간단한 코드 세션에서 이런 최적화는 아무것도 아니지만 귀속을 처리할 때 큰 문제를 해결했다. 특히 귀속이 수천 수백 개의 창고 프레임을 초래할 수 있을 때.TCO가 있으면 엔진은 같은 창고 프레임으로 모든 종류의 호출을 실행할 수 있습니다!
반복은 JavaScript의 복잡한 주제입니다.TCO가 없다면 엔진은 임의의 제한을 통해 귀속 창고의 깊이를 정하고 메모리의 소모를 방지하기 위해 멈춰야 하기 때문이다.TCO가 있으면 나중에 호출된 귀속 함수는 본질적으로 임의로 실행할 수 있다. 더 이상 추가 메모리를 사용할 필요가 없고 메모리가 넘치는 문제도 없기 때문이다.
다음은 꼬리 귀속으로 전형적인 곱셈 함수를 실현한다.
//
function factorial(n) {
if (n<2) return 1
var res = 1
for (var i = n; i > 1; i--) {
res *= i
}
return res
}
//
function factorial(n) {
function fact(n, res) {
if (n < 2) return res
return fact(n-1, n*res)
}
return fact(n, 1)
}
factorial(5) // 120
주의: TCO는 실제 꼬리 호출이 있는 경우에만 사용됩니다. 만약에 꼬리 호출이 없는 함수를 썼다면 성능은 일반 프레임 창고에 분배된 상황으로 돌아가고 엔진은 이러한 귀속 호출 창고에 대한 제한도 유효합니다.총결산
일반적으로 꼬리 호출 제거는 선택할 수 있고 사용할 수도 있고 사용하지 않을 수도 있다.그러나 함수 프로그래밍 언어에서 언어 표준은 일반적으로 컴파일러나 운행 플랫폼에 마지막 호출 제거를 요구한다.이것은 프로그래머로 하여금 성능을 잃지 않고 순환을 대체할 수 있게 한다.ES6가 엔진에 대해 자유롭게 결정하지 않고 TCO를 실현하도록 요구하는 이유는 TCO 부족으로 인해 일부 자바스크립트 알고리즘이 호출 창고 제한을 두려워하여 귀속을 통해 실현될 확률을 낮추기 때문이다.
만약 모든 상황에서 엔진이 TCO가 부족하여 성능만 떨어뜨렸다면 그것은 ES6가 요구하는 것이 되지 않았을 것이다.그러나 TCO가 부족하면 일부 프로그램을 실현할 수 없기 때문에 이것은 숨겨진 실현 디테일이 아니라 중요한 언어 특성이 되었다.ES6는 자바스크립트 개발자가 지금부터 ES6+에 맞는 모든 브라우저에서 이 최적화에 의존할 수 있도록 보장합니다.이것은 JavaScript 성능에 있어서 승리입니다.
참고 문헌
《 네가 모르는 자바스크립트. - 중권. 》
이 ES6 꼬리 호출 최적화 사용에 관한 글은 여기까지 소개되었습니다. 더 많은 ES6 꼬리 호출 최적화 내용은 저희 이전의 글을 검색하거나 아래의 관련 글을 계속 찾아보세요. 앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
(Javascript) ES6의 주요 특징 정리let을 사용하면 선언한 변수는 블록안에서만 유효하게 된다. const 역시 마찬가지로 블록스코프를 따른다 .const 와 let의 차이점은 const 는 상수로 값을 할당한다는 점이다. 따라서 값을 변경시키려고 하...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.