意外在ES6代理中设置陷阱行为

let ar = []; let p = new Proxy(new Map(), { get: (o, k) => { ar.push(1) return Reflect.get(o, k).bind(o) }, set: (o, k, v) => { ar.push(2) return Reflect.set(o, k, v) } }); p.set(1, 2) p.get(1) console.log(ar) //Outputs [1,1] 

我试图拦截两个集合,并得到一个Map对象的操作。 我没有办法试图扩展/子类的地图。 在代理Map对象的过程中,我遇到了这个奇怪的意外行为,在上面的代码中没有触发set trap,而是get trap被激发了两次!

我进一步按照以下方式loggingget陷阱中的k(key)值;

 //same code above get: (o, k) => { console.log(k) //Logs set and then get! return Reflect.get(o, k).bind(o) } //same code below 

我期望的行为是在get陷阱中将数组设置为[2,1]console.log(k)以实际输出密钥的值。

我想知道为什么会发生这种情况,在这里我已经遇到了一些类似于这个地图的问题,但是没有一个会导致为什么会发生这种情况。

我的最终目标是在设定的陷阱中发起一个事件。 我使用代理的东西是为了使用? 如果不是,我应该采取什么方法? 我是否应该放弃使用一个映射到一个对象文字,即使它会带来所有使用的缺点? 例如:没有长度属性,仅string属性,没有强制唯一键等

更新 :越来越多的我深入这个代理地图,我遇到的问题越来越多。 现在看来,ES6 Proxy API对待地图的方式与普通对象相同。 Vill的回答和我的挖掘支持。 我为什么这么说? 阅读以下;

 //same code above get: (o, k) => { if(k === 'tray') return ']' return Reflect.get(o, k).bind(o) } //same code below p.tray //returns ] 

上面的代码理论上不应该成功,对吧? 就好像Proxy在拦截Maps时也使用相同的逻辑截取对象操作一样! 如;

 ///--While the following---// let m = new Map(); m.set('tray', ']') m.tray //undefined 

Vill的答案是,Proxy将Map.prototype.set标识为第一读取集,然后将其作为函数调用。 这并不意味着在原来的代码(在最上面)写的设置陷阱不会拦截修改/设置地图的属性,实际上隐式/原生地图到Map.prototype.set是用来代替我们通过Proxy授予的Reflect.set

这不是所有这些都进一步强化了代理和地图混合不好的事实吗? 我走错路了吗? 我误解了什么? 代理应该像对待任何其他对象一样对待地图吗?

这不是bug是function(笑话)。

你应该明白代理的.get和.set是做什么的。 获取将拦截任何对象的阅读尝试。 让我们来看看你的例子:

 p.set(1,2) p.get(1) 

在第一行我们:从名称设置的对象属性读取 ,然后尝试作为函数调用它

在第二行,我们从名称为get的对象属性中读取 ,然后尝试将其作为函数调用。

如果你会尝试这个代码:

 p.val = 5; 

那么你会尝试设置5到名字为val的目标,并且setter将会被触发。

这是如何代理的二传手和getter工作。

因此,要实现所需的行为,请检查属性名称并返回该函数一些额外的实现。 并且不要忘记调用原始function。

这样的话:

 get: (o, k) => { if (k==='get') return Reflect.get(o, k).bind(o); if (k==='set') return function(v){Reflect.set(o, k, v)} } 

希望这可以帮助。

更新:

 let obj = { take: (v) => v }; let handler = { get: (target, key) => { if (key === 'take') { return function(v) { console.log(`logger says: function ${key} was called with argument: ${v}`); } return target[key]; } } }; let proxy = new Proxy(obj, handler); proxy.take(5); proxy.take(3); 
Interesting Posts