I have an ES2015 class, call it Foo
, which has at least two member functions, bar
and baz
. In bar
there is a call to setTimeout
whose first parameter is this.baz
. Works fine up to here, I inspected it in the debugger, and this
does refer to the instance of my class. (Actually since I'm using babel, I end up with a _this = this
substitution beforehand but anyway the right thing is being passed into the setTimeout
, confirmed.)
The problem is when the setTimeout
callback fires, it calls the right function baz
, but the this
inside of baz
the value of this
refers to Window
instead. Babel tries to do a _this2 = this
at the beginning of baz
but it seems to be too late already.
So my problem appears, somewhere in between the function baz
being passed and the time it is called, it loses its this
scoping. My question is, am I doing something wrong with ES2015 or babel here? I feel like this is a common enough use case that it shouldn't require too much strain. Personally I'd like to do this all with Promise
but due to business requirements I can't add too much new JS stuff at once.
Alternatively, is there a standard idiom for passing the scope of this
as I need here? It seems really messy and counter-intuitive to have to pass the calling object of a member function in as one of its parameters.
Here's a minimal working example for reference:
class Foo{
bar(){
setTimeout(this.baz, 1000);
}
baz(){
console.log("this message should repeat roughly once per second");
this.bar();
}
}
And here's a screenshot of me using it on a very simple page, along with the error message:
Edit: I have to object to my question being marked as a duplicate. Of course I had searched seen the setTimeout
questions before asking this one. However the ES2015 and class
-based aspect of my question is relevant and important, since the ES2015 syntax transformation of classes in babel changes the apparent behavior of this
. My question was about whether there is another ES2015 design pattern to handle this, and why the intuitive class
abstraction/encapsulation was being broken by passing a member function as a first-class value to be called externally. The most significant insight I gained was gleamed from a comment below by @FelixKing which I'll repeat here for posterity (in case anyone else is wondering):
Whether or not autobind class methods (like in Python) was discussed but ultimately decided against, likely to keep consistency with the rest of the language. There is also the question whether it would be possible to autobind methods without memory/performance impact.