Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript getter for all properties

Long story short: I'm in a situation where I'd like a PHP-style getter, but in JavaScript.

My JavaScript is running in Firefox only, so Mozilla specific JS is OK by me.

The only way I can find to make a JS getter requires specifying its name, but I'd like to define a getter for all possible names. I'm not sure if this is possible, but I'd very much like to know.

like image 831
arantius Avatar asked Jun 15 '09 00:06

arantius


People also ask

What does .get do in JavaScript?

Getters give you a way to define a property of an object, but they do not calculate the property's value until it is accessed. A getter defers the cost of calculating the value until the value is needed. If it is never needed, you never pay the cost.

Should I use getters and setters in JavaScript?

Conclusion. You don't necessarily have to use getters and setters when creating a JavaScript object, but they can be helpful in many cases. The most common use cases are (1) securing access to data properties and (2) adding extra logic to properties before getting or setting their values.

What are JavaScript accessors?

In JavaScript, accessor properties are methods that get or set the value of an object. For that, we use these two keywords: get - to define a getter method to get the property value. set - to define a setter method to set the property value.

Are getters and setters bad?

Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details. What if you need to change the accessed field's type? You also have to change the accessor's return type.


6 Answers

Proxy can do it! I'm so happy this exists!! An answer is given here: Is there a javascript equivalent of python's __getattr__ method? . To rephrase in my own words:

var x = new Proxy({}, {
  get(target, name) {
    return "Its hilarious you think I have " + name
  }
})

console.log(x.hair) // logs: "Its hilarious you think I have hair"

Proxy for the win! Check out the MDN docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Works in chrome, firefox, and node.js. Downsides: doesn't work in IE - freakin IE. Soon.

like image 106
B T Avatar answered Oct 20 '22 17:10

B T


You can combine proxy and class to have a nice looking code like php:

class Magic {
    constructor () {
        return new Proxy(this, this);
    }
    get (target, prop) {
        return this[prop] || 'MAGIC';
    }
}

this binds to the handler, so you can use this instead of target.

Note: unlike PHP, proxy handles all prop access.

let magic = new Magic();
magic.foo = 'NOT MAGIC';
console.log(magic.foo); // NOT MAGIC
console.log(magic.bar); // MAGIC

You can check which browsers support proxy http://caniuse.com/#feat=proxy.

like image 23
Ali Avatar answered Oct 20 '22 17:10

Ali


The closest you can find is __noSuchMethod__ (__noSuchMethod__ is deprecated), which is JavaScript's equivalent of PHP's __call().

Unfortunately, there's no equivalent of __get/__set, which is a shame, because with them we could have implemented __noSuchMethod__, but I don't yet see a way to implement properties (as in C#) using __noSuchMethod__.

var foo = {
    __noSuchMethod__ : function(id, args) {
        alert(id);
        alert(args);
    }
};

foo.bar(1, 2);
like image 27
Ionuț G. Stan Avatar answered Oct 20 '22 18:10

Ionuț G. Stan


Javascript 1.5 does have getter/setter syntactic sugar. It's explained very well by John Resig here

It's not generic enough for web use, but certainly Firefox has them (also Rhino, if you ever want to use it on the server side).

like image 36
Javier Avatar answered Oct 20 '22 19:10

Javier


If you really need an implementation that works, you could "cheat" your way arround by testing the second parameter against undefined, this also means you could use get to actually set parameter.

var foo = {
    args: {},

    __noSuchMethod__ : function(id, args) {
        if(args === undefined) {
            return this.args[id] === undefined ? this[id] : this.args[id]
        }

        if(this[id] === undefined) {
            this.args[id] = args;
        } else {
            this[id] = args;
        }
    }
};
like image 31
Vengarioth Avatar answered Oct 20 '22 17:10

Vengarioth


If you're looking for something like PHP's __get() function, I don't think Javascript provides any such construct.

The best I can think of doing is looping through the object's non-function members and then creating a corresponding "getXYZ()" function for each.

In dodgy pseudo-ish code:

for (o in this) {
    if (this.hasOwnProperty(o)) {
        this['get_' + o] = function() {
            // return this.o -- but you'll need to create a closure to
            // keep the correct reference to "o"
        };
    }
}
like image 38
nickf Avatar answered Oct 20 '22 19:10

nickf