Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/407.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用代理观察地图的更改_Javascript_Proxy_Ecmascript 6 - Fatal编程技术网

Javascript 使用代理观察地图的更改

Javascript 使用代理观察地图的更改,javascript,proxy,ecmascript-6,Javascript,Proxy,Ecmascript 6,我使用MapJavaScript对象。我想观察使用代理对象对地图实例的更改。但是,无论我尝试向代理提供什么处理程序对象,我都会在不兼容的接收器上始终得到调用的错误Method Map.prototype.set。我做错了什么?我希望使用的惯用示例如下所示 var map = new Map(); var proxy = new Proxy(map, { set(obj, prop, value) { console.log(value); } }); proxy.

我使用MapJavaScript对象。我想观察使用代理对象对地图实例的更改。但是,无论我尝试向代理提供什么处理程序对象,我都会在不兼容的接收器上始终得到调用的错误
Method Map.prototype.set
。我做错了什么?我希望使用的惯用示例如下所示

var map = new Map();
var proxy = new Proxy(map, {
    set(obj, prop, value) {
        console.log(value);
    }
});
proxy.set(1, 1); --> error

我还尝试为
apply
设置一个处理程序,但没有任何效果。

首先,请理解,您的错误也会在

var map = new Map();
var proxy = new Proxy(map, {});
proxy.set(1, 1);
它与您使用的
集合(对象、道具、值)
无关

为什么失败 要进一步打破这一点,请理解这与执行基本相同

var map = new Map();
var proxy = new Proxy(map, {});
Map.prototype.set.call(proxy, 1, 1);
这也是错误。您正在为
Map
实例调用
set
函数,但将
Proxy
而不是
Map
实例传递给它

这就是问题的核心所在
Map
s使用专门与
Map
对象本身关联的专用内部插槽存储数据。代理的行为不是100%透明的。它们允许您截取对象上的一组特定操作,并在操作发生时执行逻辑,这通常意味着将该逻辑代理到其他对象,在您的情况下是从
代理
映射

不幸的是,对于您的情况,代理访问映射实例的私有内部插槽不是可以被拦截的行为之一。你可以想象一下

var PRIVATE = new WeakMap();
var obj = {};

PRIVATE.set(obj, "private stuff");

var proxy = new Proxy(obj, {});

PRIVATE.get(proxy) === undefined // true
PRIVATE.get(obj) === "private stuff" // true
因此,由于对象作为
this
传递到
Map.prototype.set
不是真实的映射,因此它无法找到所需的数据,并将引发异常

解决方案 这里的解决方案意味着您实际上需要将正确的
this
传递到
Map.prototype.set

对于代理,最简单的方法是实际拦截对
.set
的访问,例如

var map = new Map();

var proxy = new Proxy(map, {
  get(target, prop, receiver) {
    // Perform the normal non-proxied behavior.
    var value = Reflect.get(target, prop, receiver);

    // If something is accessing the property `proxy.set`, override it
    // to automatically do `proxy.set.bind(map)` so that when the
    // function is called `this` will be `map` instead of `proxy`.
    if (prop === "set" && typeof value === "function") value = value.bind(target);

    return value;
  }
});

proxy.set(1, 1); 
当然,这并没有解决您关于拦截对
.set
的实际调用的问题,因此您可以对此进行扩展

var map = new Map();

var proxy = new Proxy(map, {
  get(target, prop, receiver) {
    var value = Reflect.get(target, prop, receiver);
    if (prop === "set" && typeof value === "function") {
      // When `proxy.set` is accessed, return your own
      // fake implementation that logs the arguments, then
      // calls the original .set() behavior.
      const origSet = value;
      value = function(key, value) {
        console.log(key, value);

        return origSet.apply(map, arguments);
      };
    }
    return value;
  }
});

proxy.set(1, 1);

您在代码片段中所做的任何事情都不会首先触发
设置
陷阱。如果执行
newproxy(new Map,{}),代码也会复制。set(1,1)
您既没有为代理分配属性,也没有将其作为函数调用,这就是
set
apply
陷阱都不存在的原因work@Bergi唉,我找了又找不到好的副本,唉,代理将不会持有
Map
的方法,比如
entries()
?@MaorBane,这些方法应该可以正常工作。