In the following code, I would expect printHello to be called twice (once from go() and once from runTask()):
class Hello {
task = undefined;
runTask() {
console.log("Task is", this.task);
this.task();
}
printHello() {
console.log("Hello");
}
go() {
this.task = this.printHello;
console.log("Set task to", this.task);
setTimeout(this.runTask, 0); // Fails
// setTimeout(() => this.runTask(), 0); // Works
}
};
const hello = new Hello();
hello.go(); // Says `this.task` is undefined, but then...
hello.runTask(); // ... running it manually works fine
In my mind:
go()
task field/property on that instance to printHellorunTask after the timeoutI would expect that runTask would be called with task set to printHello, but it's actually undefined in the setTimeout call. However, if I just call runTask directly on my hello instance it works fine. Also, if I replace the setTimeout call with a lambda it works fine.
It seems clear it's a stale closure type of issue, I just don't have a great mental model or rulebook that would prevent me from writing code like this in the future and then be perplexed about why it wasn't working.
I was thinking that this would be captured when passing runTask, which should then point to a valid task, but that's not the case.
I'd really appreciate some insight about exactly why this doesn't work and requires the lambda version to be used.