Javascript 同一目标具有多个代理对象的表观污染
我试图在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
集合
和获取
处理程序中的接收器
对象并从中访问。但是,当我检查生成的代理时,所有代理都具有我希望已分配给上次创建的代理的属性集
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
是什么?提示:您不能在代理本身上存储任何内容。