You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建带私有属性的可调用对象,如何替代废弃的arguments.callee?

实现带私有字段的可调用类对象(替代arguments.callee)

核心方案

通过绑定类方法+Proxy拦截(或直接挂载实例属性到函数)的方式,实现既能直接调用、又能保留类私有字段语法的可调用对象,完全规避废弃的arguments.callee。

方案一:Proxy拦截实现(更灵活)

class CallableObject extends Function {
  constructor() {
    super('return this._call(...arguments)');
    // 绑定_call方法的this指向实例
    this._call = this._call.bind(this);
    // 通过Proxy拦截apply操作,将调用指向_call方法
    return new Proxy(this, {
      apply(target, _, args) {
        return target._call(...args);
      }
    });
  }

  _call(x) {
    console.log(`对象被直接调用,参数:${x}`);
    // 直接访问私有字段
    console.log(`私有数据:${this.#data}`);
  }

  #data = '默认私有值';

  get data() {
    return this.#data ??= '初始化后的值';
  }

  set data(val) {
    this.#data = val;
  }
}

// 使用示例
const callable = new CallableObject();
callable('test'); // 输出:对象被直接调用,参数:test;私有数据:默认私有值
callable.data = '更新后的私有值';
console.log(callable.data); // 输出:更新后的私有值

方案二:直接挂载实例到函数(更简洁)

如果不需要额外的代理拦截逻辑,可以直接将类实例的属性和方法挂载到绑定后的函数上:

class CallableObject {
  constructor() {
    // 绑定_call方法到实例,作为可调用入口
    const callableFn = this._call.bind(this);
    // 将类实例的所有属性、方法挂载到函数上
    Object.assign(callableFn, this);
    return callableFn;
  }

  _call(x) {
    console.log(`调用成功,参数:${x}`);
    console.log(`当前私有数据:${this.#data}`);
  }

  #data = '初始私有数据';

  get data() {
    return this.#data;
  }
}

// 使用示例
const callable = new CallableObject();
callable('hello'); // 输出:调用成功,参数:hello;当前私有数据:初始私有数据
console.log(callable.data); // 输出:初始私有数据

方案优势

  • 完全摆脱arguments.callee,支持严格模式,符合现代JS规范
  • 保留类的私有字段语法,无需改用IIFE实现私有变量,代码结构更清晰
  • 两种方案可根据需求选择,Proxy方案支持额外的调用拦截逻辑,挂载方案更轻量化

内容的提问来源于stack exchange,提问作者Shaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 22:30:19