Reputation: 10201
I have a simple proxy object:
const myProxy = new Proxy(
/* myTarget */
{
test: 2,
},
/* myHandler */
{
get(target, prop, proxy)
{
if (prop in this && this[prop] instanceof Function)
return this[prop](target); //getter
return target[prop]; //value
},
myGetter(target)
{
return ++target.test
}
}
);
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);
Is there a way make myGetter
property as a true getter?
My attempt failed, because I don't know how to access myTarget
from within the getter:
const myProxy = new Proxy(
/* myTarget */
{
test: 2,
},
/* myHandler */
{
get(target, prop, proxy)
{
if (prop in this)
return this[prop]; //getter
return target[prop]; //value
},
get myGetter()
{
return ++target.test; //target undefined
}
}
);
console.log("test before", myProxy.test);
console.log("blah", myProxy.myGetter);
console.log("test after", myProxy.test);
The reason why I need this is because I have multiple functions inside the handler and I need to determine which one needs to be executed within handler itself (myGetter
), or should be returned as function reference (myFunc
), where it can also accept additional data as arguments, so I'm using prop instanceof Function
to check if it's a function or not:
const myProxy = new Proxy(
/* myTarget */
{
test: 2,
},
/* myHandler */
{
get(target, prop, proxy)
{
if (prop in this)
{
if (this[prop] instanceof Function)
return (args) => this[prop](target, args); //function
return this[prop]; //getter
}
return target[prop]; //value
},
get myGetter()
{
return ++target.test; //target undefined
},
myFunc(target, value)
{
return target.test * value;
}
}
);
console.log("myFunc", myProxy.myFunc(3));
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);
I could think of several work arounds, for example hard code names of functions:
const myProxy = new Proxy(
/* myTarget */
{
test: 2,
},
/* myHandler */
{
get(target, prop, proxy)
{
if (prop in this)
{
if (["myFunc"].includes(prop)) // function
return (args) => this[prop](target, args);
return this[prop](target); // getter
}
return target[prop];
},
myGetter(target)
{
return ++target.test
},
myFunc(target, value)
{
return target.test * value;
}
}
);
console.log("myFunc", myProxy.myFunc(3));
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);
Or separate functions into groups:
const myProxy = new Proxy(
/* myTarget */
{
test: 2,
},
/* myHandler */
{
get(target, prop, proxy)
{
if (prop in this._myFuncs)
return (args) => this._myFuncs[prop](target, args);
if (prop in this._myGetters)
return this._myGetters[prop](target);
return target[prop];
},
_myGetters:
{
myGetter(target)
{
return ++target.test
},
},
_myFuncs:
{
myFunc(target, value)
{
return target.test * value;
},
}
}
);
console.log("myFunc", myProxy.myFunc(3));
console.log("test before", myProxy.test);
console.log("myGetter", myProxy.myGetter);
console.log("test after", myProxy.test);
For education purpose any suggestions how to make true getter to work in Proxy?
Upvotes: 0
Views: 936
Reputation: 370789
I don't think the handler object should have nonstandard properties on it - it'd make more sense for it to only have the traps that it's expected to have. To have collection of properties for traps, either hard-code those properties (which is inflexible and not so nice) or use a separate object structure for those properties. With a separate object in the proxy closure, checking whether the property exists on the object and then .call
ing it with target if it's a getter is easy.
const makeProxy = (target, customProperties) => {
return new Proxy(
target, {
get(target, prop, proxy) {
if (prop in customProperties) {
// Invoke getter if it exists on customProperties
const { get } = Object.getOwnPropertyDescriptor(customProperties, prop);
if (get) {
return get.call(target);
}
}
// Otherwise return original object value or getter
return target[prop];
},
}
);
};
const proxy = makeProxy({
test: 2,
}, {
get myGetter() {
return ++this.test
}
});
console.log("test before", proxy.test);
console.log("blah", proxy.myGetter);
console.log("test after", proxy.test);
Upvotes: 1