setTimeout scope issue
Just in case anyone reads this, the new javascript syntax allows you to bind a scope to a function with "bind":
window.setTimeout(this.doSomething.bind(this), 1000);
Probably because this
isn't preserved in the timeout callback. Try:
var that = this;
...
var timer3 = setTimeout(function() {
that.alive = true;
...
Update (2017) - or use a lambda function, which will implicitly capture this
:
var timer3 = setTimeout(() => {
this.alive = true;
...
It's because this
in the setTimeout
handler is referring to window
, which is presumably not the same value as referenced by this
outside the handler.
You can cache the outer value, and use it inside...
var self = this;
var timer3 = setTimeout((function() {
self.alive = true;
Console.log("alive!");
}),3000);
...or you can use ES5 Function.prototype.bind
...
var timer3 = setTimeout((function() {
this.alive = true;
Console.log("alive!");
}.bind(this)),3000);
...though if you're supporting legacy implementations, you'll need to add a shim to Function.prototype
.
- MDN
Function.prototype.bind
patch
...or if you're working in an ES6 environment...
var timer3 = setTimeout(()=>{
this.alive = true;
Console.log("alive!");
},3000);
Because there's no binding of this
in Arrow functions
.
You have to be careful with this
. You need to assign your this
in the outer scope to a variable. The this
keyword always refers to the this
of the current scope, which changes any time you wrap something in function() { ... }
.
var thing = this;
thing.alive = false;
Console.log("death!");
var timer3 = setTimeout((function() {
thing.alive = true;
Console.log("alive!");
}),3000);
This should give you better success.
Update 2019-10-09: The original answer is true, but another option is now available for recent versions of JavaScript. Instead of using function
, you can use an arrow function instead, which does not modify this
:
this.alive = false;
Console.log("death!");
var timer3 = setTimeout(() => {
this.alive = true;
Console.log("alive!");
}), 3000);
This is supported from ES6 forward, which is part of all current browsers but IE (of course), I think. If you are using a modern framework to build your project via Babel or whatever, the framework should make sure this works as expected everywhere.