Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/36.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_Node.js_Ecmascript 6_Proxy Pattern - Fatal编程技术网

Javascript 同一目标具有多个代理对象的表观污染

Javascript 同一目标具有多个代理对象的表观污染,javascript,node.js,ecmascript-6,proxy-pattern,Javascript,Node.js,Ecmascript 6,Proxy Pattern,我试图在JavaScript中为同一个目标对象创建多个代理包装器,每个包装器的属性稍有不同,这会影响包装功能的运行方式。这些属性被分配给集合和获取处理程序中的接收器对象并从中访问。但是,当我检查生成的代理时,所有代理都具有我希望已分配给上次创建的代理的属性集 const obj = {}; const proxies = ['one', 'two'].map(name => { console.log(`proxy ${name}`); const proxy = new Pr

我试图在JavaScript中为同一个目标对象创建多个代理包装器,每个包装器的属性稍有不同,这会影响包装功能的运行方式。这些属性被分配给
集合
获取
处理程序中的
接收器
对象并从中访问。但是,当我检查生成的代理时,所有代理都具有我希望已分配给上次创建的代理的属性集

const obj = {};

const proxies = ['one', 'two'].map(name => {
  console.log(`proxy ${name}`);

  const proxy = new Proxy(obj, {
    get: (target, prop, receiver) => {
      if (prop === 'name') { return receiver.name; }

      return target[prop];
    },
    set: (target, prop, val, receiver) => {
      if (prop === 'name') {
        console.log(`setting name ${val} on receiver`);
        Object.defineProperty(receiver, prop, {
            value: val,
            configurable: true,
            enumerable: true}
        );
      } else {
        console.log(`setting ${prop} ${val} on target`);
        target[prop] = val;
      }

      return true;
    }
  });

  proxy.name = name;

  return proxy;
});

console.log();
console.log(proxies);
我的预期结果:
[{name:'one'},{name:'two'}]

实际结果:
[{name:'two'},{name:'two'}]
。尽管它们看起来相同,但严格来说并不相等


如果省略
const obj
并使用
新代理({},…)
创建对象,我会得到预期的结果——一个代理
one
和一个代理
two
,可能是因为它们之间没有共享目标引用。那么:到底是什么?根据我的理解,使用
接收器
存储
名称
应该可以防止它传播到目标对象,但它似乎还是这样做了。

直接在代理上设置属性时,似乎会发生这种情况。该行为与实例化多个代理无关;创建单个代理并设置其
名称
也会污染目标

使用继承对象并将其原型设置为代理,如相关问题的中所述,不会污染代理的目标。

您的代码片段

Object.defineProperty(receiver, prop, {
    value: val,
    configurable: true,
    enumerable: true}
);
不会做你(我认为)期望它做的事。由于
receiver
这里是代理对象,因此属性定义也将被代理到
target
,这意味着if/else中的分支之间几乎没有区别。如果您希望为每个代理对象存储一个唯一的名称,那么在这种情况下最简单的方法就是使用闭包的作用域,例如

const proxies = ['one', 'two'].map(name => {
  console.log(`proxy ${name}`);

  const proxy = new Proxy(obj, {
    get: (target, prop, receiver) => {
      if (prop === 'name') { return name; }

      return Reflect.get(target, prop, receiver);
    },
    set: (target, prop, val, receiver) => {
      if (prop === 'name') {
        name = val;
        return true;
      }

      return Reflect.set(target, prop, val, receiver);
    },
    ownKeys: (target) => {
      return Reflect.ownKeys(target).concat('name');
    },
    getOwnPropertyDescriptor: (target, prop) => {
      if (prop === "name") return { enumerable: true, writable: true, configurable: true, value: name };

      return Reflect.getOwnPropertyDescriptor(target, prop);
    },
  });

  return proxy;
});

或者,作为处理程序对象上的一个属性,而不是闭包范围变量。您希望值存储在何处,您希望
receiver
是什么?提示:您不能在代理本身上存储任何内容。