I have a setTimeout defined inside of a function that controls the player's respawn (i am creating a game):
var player = { ... death:(function() { this.alive = false; Console.log("death!"); var timer3 = setTimeout((function() { this.alive = true; Console.log("alive!"); }),3000); }), ... }
When it executes, I read in the console, "death!" and 3 seconds later "alive!". However, alive
is never really set back to true, because if i write player.alive
in the console, it returns false
. How come i can see "alive!" but the variable is never set back to true?
No significant effect at all, setTimeout runs in an event loop, it doesn't block or harm execution.
No, you can't be absolutely certain of anything, and javascript timers aren't very accurate either, but most of the time they are accurate enough, and will execute the function close enough to the set time.
Browsers including Internet Explorer, Chrome, Safari, and Firefox store the delay as a 32-bit signed integer internally. This causes an integer overflow when using delays larger than 2,147,483,647 ms (about 24.8 days), resulting in the timeout being executed immediately.
Explanation: setTimeout() is non-blocking which means it will run when the statements outside of it have executed and then after one second it will execute. All other statements that are not part of setTimeout() are blocking which means no other statement will execute before the current statement finishes.
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.
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
.
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
.
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