Javascript Proxy set() локальное свойство унаследованных объектов

Согласно MDN, handler.set() может перехватить унаследованное присваивание свойства:

Object.create(proxy)[foo] = bar;

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

var base = {
 foo: function(){
  return "foo";
 }
}

var proxy = new Proxy(base, {
 set: function(target, property, value, receiver){
  console.log("called: " + property + " = " + value, "on", receiver);
  //receiver[property] = value; //Infinite loop!?!?!?!?!
  //target[property] = value // This is incorrect -> it will set the property on base.
  
  /*
   Fill in code here.
  */
  return true;
 }
})

var inherited = {}
Object.setPrototypeOf(inherited, Object.create(proxy));

inherited.bar = function(){
 return "bar";
}

//Test cases
console.log(base.foo); //function foo
console.log(base.bar); //undefined
console.log(inherited.hasOwnProperty("bar")) //true

2 ответа

После некоторых дополнительных размышлений я заметил, что он перехватывает 3 операции:

Назначение свойства: proxy[foo] = bar и proxy.foo = bar Унаследованное назначение свойства: Object.create (proxy) [foo] = bar
Reflect.set ()

но нет Object.defineProperty()уровень которого даже ниже, чем у оператора =.

Таким образом, следующие работы:

var base = {
    foo: function(){
        return "foo";
    }
};

var proxy = new Proxy(base, {
    set: function(target, property, value, receiver){
        var p = Object.getPrototypeOf(receiver);
      
        Object.defineProperty(receiver, property, { value: value });   // ***
        return true;
    }
});

var inherited = {};
Object.setPrototypeOf(inherited, Object.create(proxy));

inherited.bar = function(){
    return "bar";
};

// Test cases
console.log(base.foo);                       // function foo
console.log(base.bar);                       // undefined
console.log(inherited.bar);                  // function bar
console.log(inherited.hasOwnProperty("bar")) // true

Я вижу два варианта (возможно):

  1. Храните недвижимость в Map, сохраняя Map для различных приемников в WeakMap набранный получателем. удовлетворять get проверяя Map и возвращая отображение там, а не от объекта. (Также has.) Небольшая проблема заключается в том, что вам также необходимо прокси-приемник (не только base) для того, чтобы справиться ownKeys, Так что это может быть неосуществимым.

  2. Временно получите прокси из цепочки наследования при настройке.

Вот этот второй:

var base = {
    foo: function(){
        return "foo";
    }
};

var proxy = new Proxy(base, {
    set: function(target, property, value, receiver){
        const p = Object.getPrototypeOf(receiver); // ***
        Object.setPrototypeOf(receiver, null);     // ***
        receiver[property] = value;                // ***
        Object.setPrototypeOf(receiver, p);        // ***
        return true;
    }
});

var inherited = {};
Object.setPrototypeOf(inherited, Object.create(proxy));

inherited.bar = function(){
    return "bar";
};

// Test cases
console.log("base.foo:", base.foo); // function foo
console.log("base.bar:", base.bar); // undefined
console.log("inherited.bar:", inherited.bar); // function bar
console.log("inherited has own bar?", inherited.hasOwnProperty("bar")); // true

Другие вопросы по тегам