1

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?

2
  • 1
    You need to do const myProxyObject = new Proxy(new MyObject(), {...}). Commented Apr 21, 2017 at 16:23
  • The sample code is not even valid syntax. Commented May 11, 2024 at 19:03

3 Answers 3

4

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

Sign up to request clarification or add additional context in comments.

Comments

2

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

Comments

0

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;
}
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.