JavaScript의 초기 버전에서는 명명 된 함수 표현식이 허용되지 않았기 때문에 재귀 함수 표현식을 작성할 수 없었습니다.
// This snippet will work:
function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
}
[1,2,3,4,5].map(factorial);
// But this snippet will not:
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : /* what goes here? */ (n-1)*n;
});
이 문제를 해결하기 위해 arguments.callee
추가되었습니다.
[1,2,3,4,5].map(function(n) {
return (!(n>1))? 1 : arguments.callee(n-1)*n;
});
그러나 이것은 실제로 다른 해결책, 수신자 및 발신자 문제와 관련하여 일반적인 경우에는 인라인 및 꼬리 재귀를 불가능하게하므로 실제로는 나쁜 해결책이었습니다 (추적 등을 통해 특정 경우에 달성 할 수는 있지만 최상의 코드조차도 가능합니다) 그렇지 않으면 필요하지 않은 점검으로 인해 최적이 아님). 다른 주요 문제는 재귀 호출이 다른 this
값 을 얻는다는 것 입니다. 예를 들면 다음과 같습니다.
var global = this;
var sillyFunction = function (recursed) {
if (!recursed)
return arguments.callee(true);
if (this !== global)
alert("This is: " + this);
else
alert("This is the global");
}
sillyFunction();
어쨌든 EcmaScript 3는 다음과 같은 명명 된 함수 표현식을 허용하여 이러한 문제를 해결했습니다.
[1,2,3,4,5].map(function factorial(n) {
return (!(n>1))? 1 : factorial(n-1)*n;
});
이것은 많은 이점이 있습니다 :
으악,
그 질문은 다른 모든 것에 더해 arguments.callee.caller
또는 더 구체적 이라는 것을 깨달았습니다 Function.caller
.
어느 시점에서나 스택에서 함수의 가장 깊은 호출자를 찾을 수 있으며 위에서 언급했듯이 호출 스택을 보는 데는 하나의 주요 효과가 있습니다.
예 : 함수 f
가 알 수없는 함수를 호출하지 않을 것이라고 보장 할 수 없으면 인라인 할 수 없습니다 f
. 기본적으로 그것은 사소하게 불쾌했을 수있는 모든 호출 사이트에 많은 수의 경비원이 축적됨을 의미합니다.
function f(a, b, c, d, e) { return a ? b * c : d * e; }
js 인터프리터가 제공된 모든 인수가 호출 시점의 숫자임을 보장 할 수 없으면 인라인 코드 앞에 모든 인수에 대한 검사를 삽입하거나 함수를 인라인 할 수 없습니다.
이제이 특별한 경우에, 스마트 통역사는보다 최적의 수표를 재 배열하고 사용할 수없는 값을 검사하지 않을 수 있어야합니다. 그러나 많은 경우에 그것은 가능하지 않으므로 인라인하는 것이 불가능합니다.