Reputation: 2100
I have difficulties with using the this
keyword in a MooTools (1.3) class. The constructor assigns a value to an attribute, and a subsequently run method displays this value in an alert
popup. If I want to run this method delayed (using myfunction.delay(…)
) the popup displays undefined
.
var MyClass = new Class({
initialize: function() {
this.x = 13;
},
run: function() {
alert(this.x);
}
});
window.addEvent('domready', function() {
var m = new MyClass();
m.run(); // ``13''
m.run.delay(2000); // ``undefined''
});
After fiddling around, I managed to find the following solution:
window.addEvent('domready', function() {
var m = new MyClass();
(function() { m.run() }).delay(2000); // ``13''
});
Still, I would like to understand what’s happening here, and why simply calling m.run.delay(…)
doesn’t do the trick.
Upvotes: 1
Views: 693
Reputation: 50109
When you invoke a function as m.run()
the this
keyword will refer to the base object m
. Function.prototype.delay
however probably uses setTimeout
to invoke your delayed function.
Function.prototype.delay = function(ms) {
setTimeout(this, ms);
}
The problem with this form is that setTimeout
will invoke your function without the base object reference, so this
will refer to the global object (~ window).
The solution is to pass the object of invocation to delay
explicitly.
/**
* delay - (number) The duration to wait (in milliseconds).
* bind - (object, optional) The object that the "this" of the function
* will refer to.
* args - (mixed, optional) The arguments passed (must be an array if the
* arguments are greater than one).
*/
m.run.delay(2000, m);
Upvotes: 0
Reputation: 141879
When we call delay
on a function, that function will be executed in the context of the global object (usually window
). The solution is to wrap it inside another function and capture the object m
in the closure.
An easier way to doing this is to use the bind
parameter in the call to delay
. The bind parameter specifies what the this
value should refer to inside the function when it is invoked.
m.run.delay(2000, m);
Upvotes: 4