JavaScript getter for all properties

JavascriptFirefoxGetter

Javascript Problem Overview


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.

Javascript Solutions


Solution 1 - Javascript

Proxy can do it! I'm so happy this exists!! An answer is given here: https://stackoverflow.com/questions/1529496/is-there-a-javascript-equivalent-of-pythons-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.

Solution 2 - Javascript

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.

Solution 3 - Javascript

The closest you can find is __noSuchMethod__, 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);

Solution 4 - Javascript

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).

Solution 5 - Javascript

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

Solution 6 - Javascript

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

Solution 7 - Javascript

I ended up using a nickfs' answer to construct my own solution. My solution will automatically create get_{propname} and set_{propname} functions for all properties. It does check if the function already exists before adding them. This allows you to override the default get or set method with our own implementation without the risk of it getting overwritten.

for (o in this) {
        if (this.hasOwnProperty(o)) {
            var creategetter = (typeof this['get_' + o] !== 'function');
            var createsetter = (typeof this['set_' + o] !== 'function');
            (function () {
                var propname = o;
                if (creategetter) {
                    self['get_' + propname] = function () {
                        return self[propname];
                    };
                }
                if (createsetter) {
                    self['set_' + propname] = function (val) {
                        self[propname] = val;
                    };
                }
            })();
        }
    }

Solution 8 - Javascript

This is not exactly an answer to the original question, however this and this questions are closed and redirect here, so here I am. I hope I can help some other JS newbie that lands here as I did.

Coming from Python, what I was looking for was an equivalent of obj.__getattr__(key)and obj.__hasattr__(key) methods. What I ended up using is: obj[key] for getattr and obj.hasOwnProperty(key) for hasattr (doc).

Solution 9 - Javascript

It is possible to get a similar result simply by wrapping the object in a getter function:

const getProp = (key) => {
  const dictionary = {
    firstName: 'John',
    lastName: 'Doe',
    age: 42,
    DEFAULT: 'there is no prop like this'
  }
  return (typeof dictionary[key] === 'undefined' ? dictionary.DEFAULT : dictionary[key]);
}

console.log(getProp('age')) // 42

console.log(getProp('Hello World')) // 'there is no prop like this'

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionarantiusView Question on Stackoverflow
Solution 1 - JavascriptB TView Answer on Stackoverflow
Solution 2 - JavascriptAliView Answer on Stackoverflow
Solution 3 - JavascriptIonuț G. StanView Answer on Stackoverflow
Solution 4 - JavascriptJavierView Answer on Stackoverflow
Solution 5 - JavascriptVengariothView Answer on Stackoverflow
Solution 6 - JavascriptnickfView Answer on Stackoverflow
Solution 7 - JavascriptKevinView Answer on Stackoverflow
Solution 8 - JavascriptThéo RubenachView Answer on Stackoverflow
Solution 9 - JavascriptHynekSView Answer on Stackoverflow