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.
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.
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.
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.
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.
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.
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.
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);
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).
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;
}
}
};
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"
};
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With