Я пытаюсь создать несколько прокси-оберток для одного и того же целевого объекта в JavaScript, причем каждая отдельная оболочка имеет несколько разные свойства, которые влияют на работу обернутых функциональных возможностей. Эти свойства назначаются и получаются из объекта- receiver
в set
и обработчиках get
. Однако, когда я просматриваю сгенерированные Proxies, все они имеют набор свойств, который, как я полагаю, был назначен последнему созданному прокси.
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
и создавать свои объекты с new Proxy({},...)
я получаю ожидаемый результат - прокси one
и прокси - two
, по- видимому, так как целевая ссылка не разделяется между ними. Итак: что же? По моему мнению, использование receiver
для хранения name
должно препятствовать его распространению на целевой объект, но, похоже, это все равно.
Ваш фрагмент
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;
});
Это, похоже, происходит при настройке свойств непосредственно на прокси. Поведение не связано с созданием нескольких прокси; создание единого прокси и установка его name
также загрязняет цель.
Использование наследующего объекта с его прототипом, установленным на прокси-сервер, как подробно описано в этом ответе на соответствующий вопрос, не загрязняет цель прокси-сервера.