Преобразуйте объект Javascript в прокси (а не в его ссылку) - PullRequest
0 голосов
/ 27 августа 2018

Я могу взять объект Javascript o и создать из него новый объект Proxy:

let p = new Proxy(object, { ... })

Но есть ли способ изменить существующую ссылку на объект, чтобы отслеживать изменения в исходном объекте?В частности, есть ли способ отслеживать добавление новых ключей на объект из внешних источников?

Ответы [ 2 ]

0 голосов
/ 12 июля 2019

Спецификация Proxy поддерживает определение прокси на прототипе объекта в качестве средства проверки действий над этим объектом, когда они не существуют в экземпляре.Хотя это не полный паритет с .watch(), он учитывает упомянутый вами вариант использования, когда вы узнаете, когда добавляются новые свойства.Вот пример с комментариями о предостережениях ...

  // assuming some existing property you didn't create...
  const t = { existing: true };

  // proxy a new prototype for that object...
  const ctr = {};
  Object.setPrototypeOf(t, new Proxy(ctr, {
    get(target, key) {
      console.log('icu get');
      return Reflect.get(target, key) || ctr[key];
    },
    set(target, key, val) {
      console.log('icu set');
      // setting this container object instead of t keeps t clean, 
      // and allows get access to that property to continue being 
      // intercepted by the proxy
      Reflect.set(ctr, key, val);
      return true;
    },
    deleteProperty(target, key) {
      console.log('icu delete');
      delete ctr[key];
      return true;
    }
  }));

  // existing properties don't work
  console.log('existing');
  t.existing; // <nothing>
  t.existing = false; // <nothing>

  // new properties work
  console.log('new');
  t.test; // icu get
  t.test = 4; // icu set
  console.log(t.test); // icu get
                       // 4

  // but this doesn't work (and I think it should be a bug)
  console.log('delete');
  delete t.test; // icu get
                 // <missing icu delete>
  console.log(t.test); // 4
0 голосов
/ 27 августа 2018

Просто сначала создайте объект и сохраните ссылку на него перед созданием его прокси.

Теперь вы можете изменить любой из них (исходный объект или его прокси), а другой также получит изменения, если только выпредотвратить их на прокси:

const o = {};
const p = new Proxy(o, {
  set: function(obj, prop, value) {
    if (prop === 'd') {
      return false;
    }
    
    obj[prop] = value;
    
    return true;
  },
});

// These operations are forwarded to the target object o:
p.a = 0;
p.b = 1;

// This one is prevented by the Proxy:
p.d = true;

// Both will have two properties, a and b:
console.log(o);

// You can also mutate the original object o and the Proxy will also get those changes:
o.c = false;

// Note that now the Proxy setter is not called, so you can do:
o.d = true;

// But the Proxy still gets the change:
console.log(p);

Если вы хотите получать уведомления, когда новое свойство добавляется, удаляется или изменяется на объекте без возможности использования исходной ссылки для непосредственного изменения исходного объекта,единственный вариант, который у вас есть, - создать этот объект напрямую в качестве прокси или перезаписать исходный:

// Created from an empty object without a reference to it:
// const p = new Proxy({}, { ... });

// Overwrite the original reference:
let myObject = { a: 1, b: 2 };

myObject = new Proxy(myObject, {
  set: function(obj, prop, value) {
    if (prop in obj) {
      console.log(`Property ${ prop } updated: ${ value }`);
    } else {
      console.log(`Property ${ prop } created: ${ value }`);
    }

    obj[prop] = value;

    return true;
  },
  
  deleteProperty(obj, prop) {
    console.log(`Property ${ prop } deleted`);
  
    delete obj[prop];
  }
});

// Now there's no way to access the original object we
// passed in as the Proxy's target!

myObject.a = true;
myObject.a = false;
delete myObject.a;

Раньше был Object.prototype.watch(), но он устарел.

...