为什么代理到ES2015中的Map对象不起作用 [英] Why is Proxy to a Map object in ES2015 not working
问题描述
我通过Google Chrome 57.0.2987.133版本运行以下脚本:
var loggingProxyHandler = {get:function(targetObj,propName,receiverProxy){let ret = Reflect.get(targetObj,propName,receiverProxy);的console.log( 获取( + propName.toString()+ = + RET + ));返回ret; },set:function(targetObj,propName,propValue,receiverProxy){console.log(set(+ propName.toString()+=+ propValue +));返回Reflect.set(targetObj,propName,propValue,receiverProxy); }}; function onRunTest(){let m1 = new Map();让p1 =新代理(m1,loggingProxyHandler); p1.set(a,aval); //从这里抛出的异常} onRunTest();
:需要支持ES2015的代理的浏览器
运行时,处理程序的get trap被调用以返回Map的set函数
,然后我收到以下错误:
Uncaught TypeError :在不兼容的receiver [object Object]上调用的方法Map.prototype.setProxy.set(native)
...
我尝试从loggingProxyHandler中删除陷阱函数(使其成为一个空对象),但仍然收到相同的错误。
我的理解是,代理对象应该能够为所有原生ES5和ES2015 javascript对象生成。数组似乎在相同的代理处理程序下工作良好。
我是否误解了规格?
我的代码是否遗漏了某些东西?
Chrome中是否存在已知的错误? (我做了一个搜索,发现Chrome在这个主题上没有任何缺陷。) 解决方案
你得到错误的原因是代理没有涉及 p1.set
调用(除了 set 陷阱&mbsp;—不相关,尽管名称相同 - —正在调用以检索函数引用)。因此,一旦检索到函数引用,就会调用
this
设置为代理,而不是 Map
&mdash ;其中 Map
不喜欢。
如果您真的试图拦截 Map
,你可以通过绑定你从 get
返回的任何函数引用来修复它(参见
lines):
var loggingProxyHandler = {get:function(targetObj,propName,receiverProxy){let ret = Reflect.get(targetObj,propName,receiverProxy);的console.log( 获取( + propName.toString()+ = + RET + )); (typeof ret ===function){// *** ret = ret.bind(targetObj); // ***} // *** return ret; },set:function(targetObj,propName,propValue,receiverProxy){console.log(set(+ propName.toString()+=+ propValue +));返回Reflect.set(targetObj,propName,propValue,receiverProxy); }}; function onRunTest(){let m1 = new Map();让p1 =新代理(m1,loggingProxyHandler); p1.set(a,aval);的console.log(p1.get( A)); // } onRunTest();
需要支持ES2015的代理服务器的浏览器
p如果您的目标只是拦截但是,根本不需要代理,但是 Map#get
和 Map#set
。要么:
-
创建一个
Map
子类并实例化它。不过,假设您控制Map
实例的创建。 创建一个新的继承自 -
替换使用您自己的
Map
实例set 和 获取
方法
Map
实例,并覆盖 get
和 set
;您不必控制原始的 Map
的创建。 这里是#1:
class MyMap extends Map {set(... args){console.log(set called);返回super.set(... args); } get(... args){console.log(get called);返回super.get(... args); }} const m1 = new MyMap(); m1.set(a,aval); console.log(m1.get(a));