创建带私有属性的可调用对象,如何替代废弃的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
相关产品推荐
相关产品推荐

