Function.prototype.caller

비표준: 이 기능은 비표준이므로 실제 프로덕션에서 사용하지 마세요. 모든 사용자 환경에서 작동하지 않을 수 도 있으며, 미래에 호환성 문제가 생길 수 있습니다.

지원이 중단되었습니다: 이 기능은 더 이상 권장되지 않습니다. 일부 브라우저에서는 아직 지원할 수 있지만 관련 웹 표준에서 이미 제거되었거나 제거 과정에 있는 경우가 있으며, 호환성을 위해 유지되고 있을 수 있습니다. 사용을 피하고 가능하다면 기존 코드를 업데이트하세요. 결정을 지원할 하단의 호환성 표를 확인하세요. 이 기능은 언제든지 작동을 중단할 수 있음을 유의하세요.

참고: 엄격 모드에서 함수의 caller에 접근하면 오류가 발생합니다. 해당 API가 대체되지 않고 제거되었습니다. 이는 보안 위험을 초래하고 인라이닝 및 꼬리 호출(tail-call) 최적화와 같은 최적화의 가능성을 심각하게 제한하는 코드가 스택을 순차적으로 검사하는 것(walk the stack)을 방지하기 위한 것입니다. 자세한 설명은 arguments.callee의 사용 중단에 대한 근거에서 확인할 수 있습니다.

Function 인스턴스의 caller 접근자 속성은 이 함수를 호출한 함수를 반환합니다. 엄격 모드, 화살표, 비동기 및 제너레이터 함수의 경우 caller 속성에 액세스하면 TypeError가 발생합니다.

설명

f 함수가 최상위 코드에 의해 호출된 경우 f.caller의 값은 null이고, 그렇지 않으면 f를 호출한 함수입니다. f를 호출한 함수가 엄격 모드 함수인 경우 f.caller의 값도 null입니다.

ECMAScript 사양에 지정된 유일한 동작은 Function.prototype에 모든 get 또는 set 요청("포이즌 필 접근자"(poison pill accessor)라고 함)에 대해 무조건 TypeError가 발생하는 초기 caller 접근자가 있다는 것과 구현체에서 이 의미를 변경할 수 없는 엄격하지 않은 일반 함수를 제외한 어떤 함수에도 엄격한 모드 함수 값이 없어야 한다는 점에 유의하시기 바랍니다. caller 속성의 실제 동작은 오류를 발생시키는 것 이외의 경우 구현체에 따라 정의됩니다. 예를 들어 Chrome은 자체 데이터 속성으로 정의하는 반면, Firefox와 Safari는 초기 포이즌 필 Function.prototype.caller 접근자를 확장하여 엄격한 함수가 아닌 this 값을 특별히 처리합니다.

js
(function f() {
  if (Object.hasOwn(f, "caller")) {
    console.log(
      "caller is an own property with descriptor",
      Object.getOwnPropertyDescriptor(f, "caller"),
    );
  } else {
    console.log(
      "f doesn't have an own property named caller. Trying to get f.[[Prototype]].caller",
    );
    console.log(
      Object.getOwnPropertyDescriptor(
        Object.getPrototypeOf(f),
        "caller",
      ).get.call(f),
    );
  }
})();

// In Chrome:
// caller is an own property with descriptor {value: null, writable: false, enumerable: false, configurable: false}

// In Firefox:
// f doesn't have an own property named caller. Trying to get f.[[Prototype]].caller
// null

이 속성은 arguments 객체의 미사용 arguments.caller 속성을 대체합니다.

예제

함수의 caller 속성의 값 확인하기

아래 코드는 함수의 caller 속성 값을 확인합니다.

js
function myFunc() {
  if (myFunc.caller === null) {
    return "The function was called from the top!";
  } else {
    return `This function's caller was ${myFunc.caller}`;
  }
}

스택 재생성과 재귀

재귀의 경우에는 이 속성을 사용하여 호출 스택을 재생성할 수 없음을 유의하시기 바랍니다. 아래를 고려해보세요.

js
function f(n) {
  g(n - 1);
}
function g(n) {
  if (n > 0) {
    f(n);
  } else {
    stop();
  }
}
f(2);

stop()이 호출될 시점에서의 호출 스택은 아래와 같습니다.

f(2) -> g(1) -> f(1) -> g(0) -> stop()

아래는 참입니다.

js
stop.caller === g && f.caller === g && g.caller === f;

아래와 같이 stop() 함수에서 스택 추적을 가져오려고 시도한다면

js
let f = stop;
let stack = "Stack trace:";
while (f) {
  stack += `\n${f.name}`;
  f = f.caller;
}

루프는 절대 멈추지 않습니다.

엄격 모드에서의 caller

caller가 엄격 모드 함수라면, caller의 값은 null입니다.

js
function callerFunc() {
  calleeFunc();
}

function strictCallerFunc() {
  "use strict";
  calleeFunc();
}

function calleeFunc() {
  console.log(calleeFunc.caller);
}

(function () {
  callerFunc();
})();
// Logs [Function: callerFunc]

(function () {
  strictCallerFunc();
})();
// Logs null

명세서

어떤 표준에도 속하지 않습니다.

브라우저 호환성

BCD tables only load in the browser

같이 보기