These function are simple enough to understand — pass it a function, and a duration. After the duration has elapsed the passed function will be called once (if using setTimeout) or repeatedly (if using setInterval). Example:
var blinkInterval = window.setInterval(blink, 2000); //calls blink every two seconds function blink() { //flash a light } function killBlinky() { window.clearInterval(blinkInterval); }
It is possible to cancel the blinking by calling clearInterval
.
Very frequently you will find that you want to pass a parameter or context to the called function; now it gets interesting. Read on...
Mozilla describes this well. Basically, when these timer functions call your custom function, the context is set at the document root level. In the example below, self
was created so that a closure would be created around it when the anonymous function inside setInterval
is declared. If you tried to reference the Person methods directly (e.g. this.incrementReminder();
) then you would get the error message “this.incrementReminder is not a function” because this
refers to the window object, not a Person instance.
var Person = function(fullName) { this.fullName = fullName; this.reminders = 0; } Person.prototype.incrementReminder = function() { this.reminders++; } Person.prototype.toString = function() { return this.fullName + ' has been reminded ' + this.reminders + ' times.'; } Person.prototype.beginReminders = function(seconds) { var self = this; window.setInterval(function() { // BAD CODE => this.incrementReminder(); self.incrementReminder(); console.log(String(self)); }, seconds * 1000); } var craig = new Person("Craig Stronbolli"); var nancy = new Person("Nancy Lopez"); console.log(String(craig)); console.log(String(nancy)); craig.beginReminders(2); nancy.beginReminders(5);
Using Function.prototype.bind()
is a rather elegent way to handle the problem. Using the example above, replace Person.prototype.beginReminders
with this:
Person.prototype.beginReminders = function(seconds) { window.setInterval((function() { this.incrementReminder(); console.log(String(this)); }).bind(this), seconds * 1000); };
If you are using ES6 syntax, then use:
Person.prototype.beginReminders = function(seconds) { window.setInterval(() => { this.incrementReminder(); console.log(String(this)); }, seconds * 1000); };