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
Я вижу два варианта (возможно):
Храните недвижимость в
Map
, сохраняяMap
для различных приемников вWeakMap
набранный получателем. удовлетворятьget
проверяяMap
и возвращая отображение там, а не от объекта. (Такжеhas
.) Небольшая проблема заключается в том, что вам также необходимо прокси-приемник (не толькоbase
) для того, чтобы справитьсяownKeys
, Так что это может быть неосуществимым.Временно получите прокси из цепочки наследования при настройке.
Вот этот второй:
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