callee 与 caller 属性

JavaScript 中 arguments.callee 和 function.caller 的作用与用法

问题

JavaScript 中 calleecaller 的作用是什么?

解答

callee

arguments.callee 指向当前正在执行的函数本身,常用于匿名函数的递归调用。

// 匿名函数中使用 callee 实现递归
const factorial = function(n) {
  if (n <= 1) return 1;
  // arguments.callee 指向当前函数
  return n * arguments.callee(n - 1);
};

console.log(factorial(5)); // 120

caller

function.caller 返回调用当前函数的函数引用。如果在全局作用域调用,返回 null

function outer() {
  inner();
}

function inner() {
  // inner.caller 指向调用 inner 的函数
  console.log(inner.caller); // 输出 outer 函数
}

outer();

// 全局调用时
function test() {
  console.log(test.caller); // null
}
test();

完整示例

// 示例:使用 callee 实现匿名递归
const sum = function(n) {
  if (n === 1) return 1;
  return n + arguments.callee(n - 1);
};
console.log(sum(100)); // 5050

// 示例:使用 caller 追踪调用链
function a() {
  b();
}

function b() {
  c();
}

function c() {
  // 打印调用栈
  let caller = c.caller;
  while (caller) {
    console.log(caller.name); // 依次输出: b, a
    caller = caller.caller;
  }
}

a();

现代替代方案

由于 calleecaller 在严格模式下被禁用,推荐使用命名函数表达式:

"use strict";

// 使用命名函数表达式替代 callee
const factorial = function fact(n) {
  if (n <= 1) return 1;
  return n * fact(n - 1); // 直接使用函数名
};

console.log(factorial(5)); // 120

关键点

  • arguments.callee 指向当前执行的函数,用于匿名函数递归
  • function.caller 返回调用当前函数的函数,全局调用时为 null
  • 严格模式下两者都被禁用,访问会抛出 TypeError
  • 现代代码应使用命名函数表达式替代 callee
  • 这两个属性已被废弃,不建议在生产环境使用