Reputation: 123
I want to do something like this:
function x(){
var o = {};
o.__defineGetter__('y', function(){
return new Date();
});
return o.y;
}
var z = x();
console.log(z);
//Wait 1 second
console.log(z); //Date should be one second past the last printing
Of course, this doesn't work because o.y is evaluated when it is returned. I'm looking for a way to return a variable that acts as a getter. The following example gives me hope that something like this could be possible:
function x(context){
//Bind the getter to the passed in scope
context.__defineGetter__('y', function(){
return new Date();
});
}
x(this);
console.log(y);
//Wait 1 second
console.log(y); //Date is one second past last printing
Has anyone ever tried to do something like this?
Yes, I'm familiar with other ways to model similar behavior using different syntax. I just want this particular syntax to work for a special scenario.
Thanks,
Chris
Upvotes: 5
Views: 1015
Reputation: 5608
function x(){
var o = function() {};
o.__proto__ = {
valueOf: function() {
return new Date().toString();
}
};
return o;
}
var z = x();
console.log(z); // Tue Mar 13 2012 14:10:10 GMT+0200 (GTB Standard Time)
setTimeout(function() {
console.log(z); // Tue Mar 13 2012 14:10:12 GMT+0200 (GTB Standard Time)
}, 2000);
Upvotes: 2
Reputation: 29515
The answer is no, you cannot assign a value to a variable that causes the variable to act like it is a function when accessed like a variable. The closest you can come, as you pointed out in your question, is to define an property with a getter function. You cannot create a local variable of a function that works as you describe.
You can however, define a function that defines a global property with a getter function (or, rather, a property on the global object) and make it look like you did what you wanted. For exmaple, in ES5, the following will create a global variable y
that acts as you describe.
function x(n) {
Object.defineProperty(this, n, {
get: function() {
return new Date();
}
});
}
x('y')
Note this only works in non-strict mode. In strict mode, this
is would have the value undefined
.
Why you would want a variable to act like that I cannot fathom.
Upvotes: 2
Reputation: 30441
The problem here is that when you're returning o.y
in the first function, you're not returning the getter method, you're returning the Date object returned by invoking the getter method. You're then assigning that Date object to z
, so every time you console.log(z)
, you're logging that Date object, not invoking the function again.
In the second example, when you console.log(y), you're actually invoking the function each time.
A possible solution, though problably not what you're wanting to do, is to have the getter in the first example return a function. Then it would work.
function x(){
var o = {};
o.__defineGetter__('y', function(){
return function() {
return new Date();
}
});
return o.y;
}
var z = x();
console.log(z());
//Wait 1 second
setTimeout( function() {
console.log(z()); //Date is one second past last printing
}, 1000)
Getter methods are kind of a special case in Javascript because they invoke a function without the usual ()
at the end, which I suppose can be confusing because normally you'd expect o.y
to return a function rather than invoke a function.
Upvotes: 1