I am trying to solve a problem that came to my mind lately. Let's say we would want and would know how to make a point in having dynamic getters and setters in javascript, more like those in php (__get, __set). But as javascript does not have a catch-all property the only thing we could do is to provide a list of possible keys and iterate to add getters and setters on those only, and hope none other will ever come.
But the problem is not by far solved. So the next approach that came to my mind was to use a nasty hack with try
and catch
, so anytime a name would be undefined in an object to use the catch
as a getter (at least) and then resume the code, hard and maybe pointless thing to do. But from here came my second problem, in an use such as this :
console.log(g.someundefinedproperty);
the result would have been a call to console.log
showing undefined
with no exception to be ever thrown.
And then it came to me: what if I would use the original window.undefined
getter and setter, after all it must be called every time I screw up and misspell a word or something.
So I tried
Object.defineProperty(window, 'undefined', {
get : function ()
{
// functional code, including getting the caller and figuring out
// where we are, and what we have to do... easy :D
console.log('works');
},
set : function ()
{
// some couple more fine hacks here
console.log('this too');
}
});
But unfortunately the undefined
property of window is configurable : false
.
Other hacks tried were cloning the window
object except the undefined
and the inner window
property. And on the new object to define the new undefined
(please take note of the irony) and then window = mybetterwindow
;
As this did not rose any issue my hopes were high, but yet again the system failed me as window
can't be overwritten, by design.
I made a guess it has it's own getter and it's reinstanciate itself based on the prototype found in window.prototype
or even better Window.prototype
(note the uppercase).
As my final step in this experiment I had redefined undefined
on this prototype hitted run. To no avail, nothing was changed... I tryed creating a new Window()
, but Window
is not a constructor, fail!
As I have run out of ideas I find myself here writing this pleading for help.
If you have any ideas how to solve the dynamic getters and setters problem, (the existencial problem of life, universe and everything else
), in a way which does not modify in any way the... way I use the objects (and as bonus it doesn't need to break
a hole
in the fabric of time and space
) or the syntax, I entreat you to speak or forever be silent :).
But unfortunately the undefined property of window is
configurable: false
This is true only since EcmaScript 5.1. Before, it was overwritable.
what if I would use the original
window.undefined
getter and setter, after all it must be called every time I screw up and misspell a word or something.
No, it would not have worked. There is a difference between the undefined value and the global variable "undefined". The variable is not evaluated each time a undefined value is encountered (e.g. in typeof (void 0)
), only when you use it explicitly (such as in g.someprop === undefined
).
Any ideas how to solve the dynamic getters and setters problem?
There is only one solution: Proxies
. Unfortunately, it is only a harmony draft and currently only supported in Firefox' Javascript 1.8.5.
See also Is there an equivalent of the __noSuchMethod__ feature for properties, or a way to implement it in JS?, Detect when a new property is added to a Javascript object? or How to detect when a property is added to a JavaScript object? which implements a polling solution (checking for changes via setInterval
).
For a clean solution, you currently have to use an explicit getter function, which you pass the property name (g.get("someundefinedproperty")
).
What you're trying to accomplish (a global getter for any undefined property) is outside the scope of cross-browser JavaScript.
The closest functionality would be using __defineGetter__
to add a particular property to all objects:
var o = Object.prototype;
o.__defineGetter__("testo", function() { return "yo in testo"; });
alert({}.testo);
alert((new Date()).testo);
http://jsfiddle.net/NLCvs/2/
This may be useful if you can predict the name of possibly undefined properties ahead of time. Even so it's quite hacky and bad form to add an accessor to all objects for a property that might be undefined.
A better option is to refactor code when an undefined property may be accessed:
function getter(o, n) {
return typeof o[n] == 'undefined' ? 'some default value' : o[n];
}
var obj = { hello: 'world' };
alert(getter(obj, 'hello'));
alert(getter(obj, 'an_undefined_property'));
An even better option is to use a mixin to set any default properties you will need to access, for instance via jQuery.extend
var defaults = {
required: 'this property is required'
};
var my_object = {
something_else: 'this is something else'
};
var o = jQuery.extend({}, defaults, my_object);
// o.required === 'this property is required'
// o.something_else === 'this is something else'
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