使用Proxy与Reflect代理Map时size属性报错的原因
为什么代理Map时仅访问size属性会报错?
我知道Map集合拥有[[MapData]]内部槽,因此尝试用Reflect配合Proxy进行拦截,编写了如下代码:
const map = new Map(); const proxiedMap = new Proxy(map, { get(target, property, receiver) { const currentValue = Reflect.get(target, property, receiver); return typeof currentValue === "function" ? currentValue.bind(target) : currentValue; } });
调用set和get方法时代码运行正常,但访问size属性时抛出错误:
proxiedMap.set("a", 1); proxiedMap.get("a"); // 1 console.log(proxiedMap.size) // TypeError: Method get Map.prototype.size called on incompatible receiver #<Map>
我通过省略Reflect中的receiver参数解决了问题,但不清楚原因:
const proxiedMap = new Proxy(map, { get(target, property) { const currentValue = Reflect.get(target, property) return typeof currentValue === "function" ? currentValue.bind(target) : currentValue } })
问题原因解析
- Map的
size是访问器属性,它的getter函数会直接访问Map实例的[[MapData]]内部槽,而这个内部槽只能被原始的Map实例访问,代理对象并没有这个内部槽。 - 当你在
Reflect.get中传递receiver参数时,size的getter函数的this会指向receiver(也就是代理对象proxiedMap)。此时getter尝试从代理对象上读取[[MapData]],自然会触发"不兼容接收器"的错误。 - 而
set、get这些Map方法之所以没问题,是因为你在拦截时把它们绑定到了原始target(即真实的Map实例)上,调用这些方法时this始终指向原始Map,能正常访问内部槽。 - 省略
receiver参数后,Reflect.get默认会把target作为this上下文执行size的getter,此时getter的this是原始Map实例,能正常读取[[MapData]],所以不会报错。
内容的提问来源于stack exchange,提问作者LeeJaeyun
相关产品推荐
相关产品推荐

