2

I have the following class that is utilizing a Proxy for getting properties and methods:

class User extends Model {

    static table = 'users';
    _attributes = {
        id: 1,
        firstName: 'Testing',
        lastName: 'Test'
    };

    constructor() {
        return new Proxy(this, {
            get: function(target, name) {
                // proxy getting code for functions and properties
            }
        });
    }

    client() {
        return this.hasOne(Client, 'clientID');
    }
}

Within the get method of the proxy, retrieving attributes is trivial. I just check for their existence within _attributes, and return the value, otherwise null.

if (target._attributes.hasOwnProperty(propertyName)) {
    return target._attributes[name];
}

return null;

Then I can use it as:

const user = new User();
console.log(user.id); // returns 1
console.log(user.firstName); // returns "Testing"

Within the get method of proxy, I can also check if the property called was a function, and return the appropriate function as a result:

if (typeof target[name] === 'function') {
    const originalFunction = target[name];
    return function(...args) {
        return originalFunction.apply(this, args);
    };
}

Then I can use it as:

const user = new User();
user.client(); // Returns the return value of client() from the class

However, within the get function of the proxy, I am unable to differentiate between user.client() and user.client. In the first case, I want to return the result of the function. In the second case, I want to retrieve the result of the function, perform an additional step, and then return that.

In Pseudo-code:

if (property is a function call) {
    return property();
}
else if (property is a function, but not a function call) {
    return property().doSomethingElse();
}

Using a Proxy, can I tell the difference between user.client() and user.client from within the get method?

In PHP, this is possible using the magic methods __get vs __call, but I am looking for a way to do this in Javascript.

Wolfie
  • 1,369
  • 8
  • 16
  • You shouldn't use proxies for anything. They're a misfeature. Getters and setters look like they would work fine here with the same interface, even. – Ry- Oct 29 '17 at 05:54
  • @Ryan can you please elaborate on that? I'm not sure how with a getter I could call ```user.client``` and have it return the result of the function with an additional operation applied. Something like, if ```user.client()``` return just the function call, else if ```user.client``` return ```user.client().somethingElse()``` – Wolfie Oct 29 '17 at 06:01
  • You can't make `user.client` take on different values depending on whether it's called. – Ry- Oct 29 '17 at 06:24
  • @Ryan That is what I figured. Unfortunate really as other languages have support for this. – Wolfie Oct 29 '17 at 06:25
  • I don't think it's unfortunate at all – it would clash with programmer expectations about how expressions work. Providing a `user.client` getter and `user.foo('client')` method is more explicit. – Ry- Oct 29 '17 at 06:29
  • @Ryan I just like that, for instance, in Laravel you can do this. https://laravel.com/docs/5.5/eloquent-relationships ```user->client``` would return the Model, whereas ```user->client()``` returns a query builder that you can work with ```user->client()->where(...```. But thanks for suggesting the getter vs method for clarification. – Wolfie Oct 29 '17 at 06:34
  • @Ryan "You shouldn't use proxies for anything. They're a misfeature." Hahah, that has to be one of the most absurd things I've ever read on StackOverflow. True, they are often horribly misused and don't work well on built-in objects, but they still offer enormous utility. – Elliot B. Feb 08 '18 at 18:54
  • @ElliotB.: Everything you can do with a proxy is better done with a more explicit design. – Ry- Feb 08 '18 at 19:50
  • @Ryan That's not true. What's "better" is entirely subjective. – Elliot B. Feb 08 '18 at 20:06
  • @ElliotB.: Second sentence correct, first not. Anyway, feel free to do what you want. – Ry- Feb 08 '18 at 20:08

0 Answers0