javascript에서 사용되는 특별한 속성이다. 이 속성은 arguments 객체 내에서 현재 실행중인 함수에 대한 참조를 제공한다.
예를 들어 다음과 같은 재귀함수를 작성하다고 가정해보자
function factorial(n){
if(n==0){
return 1;
} else {
return n* arguments.callee(n-1);
}
}
console.log(factorial(5)); //120
위 코드에서 factorial 함수 내부에 arguments.callee
를 사용하여 재귀적으로 함수를 호출했다. 이는 arguments.callee
가 현재 실행중인 함수 factorial 에 대한 참조
를 가지고 있기 때문에 함수이름을 명시하지 않고 자기자신을 호출할 수 있다.
한편 arguments.callee는 ES5의 strict 모드
에서 사용을 금지
하고 있으면 사용한다면 TypeError가 발생한다.
arguments.callee 와 같이 ES5 strict모드에서는 사용이 금지되어 권장하지 않는다.
다음은 arguments.caller를 사용해서 함수를 호출한 함수에 대한 참조를 얻는 예시이다.
function outer(){
inner()
}
function inner(){
console.log(arguments.caller);
}
outer();
위의 예시에서 inner
함수 내부에서 arguments.caller
를 사용하여 함수를 호출한 outer
함수에 대한 참조를 출력한다.
자바스크립트는 호출스택 즉 현재 실행되고 있는 활성 함수의 체인을 검사하기 위한 기능을 제공해 왔다. 그중 하나가 arguments.callee
, arguments.caller
이다.
var factorial = (function(n){
return (n <= 1) ? 1 : (n*arguments.callee(n-1);
});
arguments.callee
로 현재 인자와 함께 호출한 함수를 참조하고 있다.
하지만 이는 특별히 좋은 방법이 아니다. 왜냐하면 함수 자신의 이름을 직접 참조하는 것이 더 간단하기 때문이다.
var factorial = (function(n){
return (n <= 1) ? 1 : (n*arguments.callee(n-1);
});
arguments.caller
는 주어진 인자 객체로 호출한 함수를 참조한다. 이 기능은 대부분의 환경에서 보안문제로 제거되었기 때문이다.
caller프로퍼티는 함수의 가장 최근의 호출자를 참조한다.
function revealCaller(){
return revealCaller.caller;
}
function start(){
return revealCaller()
}
start() === start; // ture;
이 프로퍼티를 사용하면 스택 추적, 즉 현재 호출 스택의 스냅샷을 보여주는 데이터 구조를 추출할 수 있다.
function getCallStack(){
var stack=[];
for(var f = getCallStack.caller; f; f = f.caller){ // 자신을 불러온 함수를 계속 찾아감
stack.push(f);
}
}
이 함수는 제대로 동작하는 것 처럼 보인다.
function f1(){
return getCallStack();
}
function f2(){
return f1();
}
var trace = f2();
console.log(trace) // [f1, f2]
하지만 이 getCallStack
은 쉽게 오작동 할 수 있다. 호출 스택에 함수가 두번이 상 나타나면 스택 검사 로직은 반복문내에 갇히게 된다.
function f(n){
return n === 0 ? getCallStack() : f(n-1);
}
var trace = f(1); //무한 루프
무엇이 잘못되었냐 하면, 함수 f가 재귀적으로 자기 자신을 호출하기 때문에 caller프로퍼티는 자동으로 그 참조를 다시 f로갱신
한다. 즉 나를 호출한 f가 아닌 다시 f를 가리켜서 내부 반복문 내에 영원히 갇히게 된다.
게다가 strict 모드
에서는 명시적으로 caller
나 callee
를 허용하지 않고 있다.
function f(){
"use strict"
return f.caller;
}
스택을 조사하는 이유가 오로지 디버깅 이라면 인터랙티브 디버거
를 사용하는게 더 좋다.