I have this Javascript constructor-
function TestEngine() {
this.id='Foo';
}
TestEngine.prototype.fooBar = function() {
this.id='bar';
return true;
}
TestEngine.prototype.start = function() {
this.fooBar();
}
TestEngine.prototype.startMethod = function() {
inter = setInterval(this.start, 200);
}
var test = new TestEngine();
test.startMethod();
Gives me this error -
Uncaught TypeError: Object [object global] has no method 'fooBar'
I tried console.log
and found out that when I call this.start
from within setInterval
, this
points to the window
object. Why is this so?
The this
pointer can point to one of many things depending upon the context:
new
) this
points to the newly created instance of the constructor.obj.funct()
) then the this
pointer inside the function points to the object.this
points to by using call
, apply
or bind
.this
pointer points to the global object by default. In browsers this is the window
object.In your case you're calling this.start
inside setInterval
. Now consider this dummy implementation of setInterval
:
function setInterval(funct, delay) {
// native code
}
It's important to understand that start
is not being called as this.start
. It's being called as funct
. It's like doing something like this:
var funct = this.start;
funct();
Now both these functions would normally execute the same, but there's one tiny problem - the this
pointer points to the global object in the second case while it points to the current this
in the first.
An important distinction to make is that we're talking about the this
pointer inside start
. Consider:
this.start(); // this inside start points to this
var funct = this.start;
funct(); // this inside funct (start) point to window
This is not a bug. This is the way JavaScript works. When you call a function as a method of an object (see my second point above) the this
pointer inside the function points to that object.
In the second case since funct
is not being called as a method of an object the fourth rule is applied by default. Hence this
points to window
.
You can solve this problem by binding start
to the current this
pointer and then passing it to setInterval
as follows:
setInterval(this.start.bind(this), 200);
That's it. Hope this explanation helped you understand a little bit more about the awesomeness of JavaScript.
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