Reputation: 167
I was trying to be a sneaky developer, and I done got myself lost in ES6 Proxies. Basically I wanted to capture any get or set in a property from another class I wrote and make sure they are stored somewhere else besides the object. It looks like this:
'use strict'
class MyObject()
{
superAwesomeFunction(){//super awesome code goes here}
}
const myProxyObject = new Proxy(MyObject, {
get: function(target, name, receiver)
{
if([CONDITIONS THAT MEET MY DEMANDS])
{
// deliver property values if they are
// my super cool database (if they exist)
}
// else just ya know, forward it to the actual MyObject
// property, if it's an actual property on MyObject
return target[name];
},
set: function(target, name, value)
{
if([CONDITIONS THAT MEET MY DEMANDS])
{
// set property values if they are
// to super cool database
}
else
{
// just set the value to the property, which
// gets created if it doesn't exist (WHICH IS SO COOL)
target[name] = value;
}
return true;
}
Okay the cool part about this? you can do something like:
// property that doesn't exist (yet)
console.log(myProxyObject.wholivesinapineappleunderthesea);
// but wait for it...
myProxyObject.wholivesinapineappleunderthesea = 'spongebob';
// bam! now it exists on the object, AND lives in my DB!
console.log(myProxyObject.wholivesinapineappleunderthesea);
Which, while a lot of work for something dorky, i cannot explain how happy it makes me feel. However, there is a problem with this. Remember that superAwesomeFunction() I put in MyObject()? Well whenever I try to call it now ES6 gives me this load of sadness:
myProxyObject.superAwesomeFunction is not a function
ES6 sits on a throne of LIES! It's totally there right? Okay so I'm pretty sure I'm trapping something wrong, because when I debug I see that the get section of the Proxy is actually picking up the superAwesomeFunction call (which makes sense as superAwesomeFunction is a property that contains a function (){})
HERE'S MY QUESTION: Does anybody know of any solution that will let me keep my ridiculous on the fly properties and still call my superAwesomeFunction()? Is it the apply trap?
Upvotes: 1
Views: 5827
Reputation: 855
To extend on Sam's answer.
The following succeeds:
function Foo() {
this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {});
foo.bar();
However, when the get
trap is added to the handler, "is not a function" is thrown:
function Foo() {
this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {
get: function(target, prop) {}
});
foo.bar();
The solution here is to add a typeof
check for default handling of the target's existing functions:
function Foo() {
this.bar = function() { console.log('baz'); }
}
let foo = new Proxy(new Foo(), {
get: function(target, prop) {
if (typeof target[prop] === 'function') {
return target[prop].bind(target);
}
}
});
foo.bar();
The following articles gives some more examples and provides nice boilerplate to use with Proxy handlers: Safely Extending The JavaScript Set Object Using Proxies
Upvotes: 4
Reputation: 167
Full code for answer is here, thank you everyone!
'use strict'
class MyObject()
{
superAwesomeFunction(){
console.log("this works!");
}
}
const myProxyObject = new Proxy( new MyObject(), {
get: function(target, name, receiver)
{
if([CONDITIONS THAT MEET MY DEMANDS])
{
// do something cool for yourself
}
return target[name];
},
set: function(target, name, value)
{
if([CONDITIONS THAT MEET MY DEMANDS])
{
// do something cool for yourself
}
else
{
// just set the value to the property, which
// gets created if it doesn't exist (WHICH IS SO COOL)
target[name] = value;
}
return true;
}
});
Upvotes: 0
Reputation: 8127
It is a little syntax error there ... you are wrapping the proxy around the raw class, not an object.
Try:
const myProxyObject = new Proxy(new MyObject(), { ... });
This should be ok. For example:
> class Blah {
... run() {
..... console.log('yay')
..... }
... }
[Function: blah]
> myProx = new Proxy(new Blah(), {});
blah {}
> myProx.run()
yay
Upvotes: 2