Очевидное загрязнение несколькими прокси-объектами для одной цели

1

Я пытаюсь создать несколько прокси-оберток для одного и того же целевого объекта в 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 должно препятствовать его распространению на целевой объект, но, похоже, это все равно.

Теги:
ecmascript-6
proxy-pattern

2 ответа

2
Лучший ответ

Ваш фрагмент

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;
});
  • 0
    Или вместо переменной область замыкания как свойство объекта-обработчика.
0

Это, похоже, происходит при настройке свойств непосредственно на прокси. Поведение не связано с созданием нескольких прокси; создание единого прокси и установка его name также загрязняет цель.

Использование наследующего объекта с его прототипом, установленным на прокси-сервер, как подробно описано в этом ответе на соответствующий вопрос, не загрязняет цель прокси-сервера.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню