关于JavaScript Proxy无法捕获getter内部属性读取行为的疑问
现象底层原理
两个测试用例表现不同的核心原因是getter执行时的this指向差异:
- 普通方法测试的执行逻辑:
你调用proxy.visible()时,首先触发Proxy的get捕获器拿到visible方法,普通函数执行时的this指向调用它的对象也就是proxy实例,所以方法内访问this.hidden等价于访问proxy.hidden,会再次触发Proxy的get捕获器,最终accessList会同时记录visible和hidden两个属性。 - getter测试的执行逻辑:
你访问proxy.visible触发Proxy的get捕获器后,代码里调用Reflect.get(target, propertyKey)获取getter的返回值,Reflect.get如果不传入第三个参数receiver,getter执行时的this会默认指向第一个参数target,也就是未被代理的原始Store实例。所以getter内部访问this.hidden是直接读写原始对象的属性,完全绕开了Proxy,自然不会被捕获,最终accessList只会记录visible一个属性。
解决方案
只需要给Reflect.get传入Proxy get捕获器自带的第三个参数receiver即可,这个参数代表本次属性访问的接收者(也就是Proxy实例本身):
const proxy = new Proxy<Store>(new Store(), { // 新增接收receiver参数 get: (target: any, propertyKey: PropertyKey, receiver: any) => { accessList.push(propertyKey); // 把receiver传给Reflect.get return Reflect.get(target, propertyKey, receiver); }, });
修改后getter执行时的this会指向proxy实例,内部访问this.hidden就会再次触发Proxy的get捕获器,第二个测试用例的accessList最终也会等于['visible', 'hidden']。
内容的提问来源于stack exchange,提问作者Tyler Liu
相关产品推荐
相关产品推荐

