Javascript中如何使用Proxy调用对象方法且避免无限递归
栈溢出原因
你写的逻辑存在两个核心问题:
get捕获器中错误使用receiver参数:receiver本身就是你创建的Proxy代理实例,在get捕获器内执行prop in receiver、receiver[prop]这类属性访问操作,会再次触发get捕获器,形成无限递归,最终导致调用栈溢出。- 逻辑设计错误:你在
get捕获器内直接执行了匹配到的函数,不符合JS常规属性访问逻辑。正常访问对象方法时应该返回方法的引用,而非当场执行,否则const method = proxy.getName这类用法会直接失效。
修复代码
修改后的代理逻辑如下:
const handlers = { get: (target, prop, receiver) => { // 所有属性判断、读取基于原始对象target,避免触发代理捕获器 if (prop in target && prop[0] !== '_') { const value = Reflect.get(target, prop, receiver); // 方法绑定原始对象作为this,保证方法内部访问私有属性不会被拦截 if (typeof value === 'function') { return value.bind(target); } return value; } throw new Error('Cannot access private or non-existent property'); } } const protect = (obj) => { return new Proxy(obj, handlers); }
测试验证:
const protectedCourse = protect(new Course('Test')); console.log(protectedCourse.getName()); // 输出预期结果 "Test"
关键修改说明
- 所有属性操作都基于原始对象
target执行,不会再触发代理的get捕获器,从根源上解决了无限递归问题。 - 访问方法时返回绑定了原始对象作为
this的函数引用,既符合JS原生属性访问逻辑,也保证方法内部访问_name这类私有前缀属性时不会被代理拦截。 - 使用
Reflect.get读取属性,保证了存在继承关系时属性访问的正确性,比直接读取target[prop]更规范。
内容的提问来源于stack exchange,提问作者Yuri Molodyko
相关产品推荐
相关产品推荐

