1

I'd like to make a python-style getattr function for a class that I'm writing, so that it can respond to a request for some attribute and react accordingly. I know that you can write a custom "getter" for a property using Object.defineProperty:

var foo = {bar: 1, baz: 2}
Object.defineProperty(foo, 'qux', 
    { 
        get: function(){
            console.log('you asked for qux!'); 
            return 5;
        }
    });
foo.qux // prints 'you asked for qux!', returns 5

I'm wondering though, is there a way to do this for an arbitrary key, so that you can do some logic based on what they asked for? For example

Object.defineGetter(foo, function(key) {
    console.log('ah, you asked for ' + key);
    if (key[0] === 'a') {
        return 0;
    } else {
        return 1;
    }
foo.apple // prints 'ah, you asked for apple', returns 0
foo.orange // prints 'ah, you asked for orange', returns 1

Is there any capability like this in JavaScript?

limp_chimp
  • 13,475
  • 17
  • 66
  • 105
  • 2
    It's not in most current JavaScript runtimes, but it's an [active proposal for ES6](http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies). – Pointy Apr 18 '14 at 23:25

1 Answers1

0

Use Function.prototype.bind:

var obj = {
    prop1: undefined,
    prop2: undefined
};

function defineGetter(obj, callback) {
    Object.keys(obj).forEach(function (key) {
        Object.defineProperty(obj, key, {
            get: callback.bind(obj, key)
        });
    });
}

defineGetter(obj, function (key) {
    if (key === "prop1") {
        return 0;
    } else if (key === "prop2") {
        return 1;
    }
});

console.log(obj.prop1); // => 0
console.log(obj.prop2); // => 1

http://jsfiddle.net/myXYU/2/

Creates a getter for every enumerable property of obj in which the first argument of the getter is pre-filled-out with the key of the property being accessed.

Only downside is that any properties added to the object later will not have have a magic getter.

Jackson
  • 9,188
  • 6
  • 52
  • 77