SetTimeout and "this" in JavaScript

I have a method that uses the setTimeout function and calls another method call. At boot time, method 2 works fine. However, after a timeout, I get the error method2 undefined. What am I doing wrong here?

Example:

 test.prototype.method = function() { //method2 returns image based on the id passed this.method2('useSomeElement').src = "http://www.some.url"; timeDelay = window.setTimeout(this.method, 5000); }; test.prototype.method2 = function(name) { for (var i = 0; i < document.images.length; i++) { if (document.images[i].id.indexOf(name) > 1) { return document.images[i]; } } }; 
+23
javascript
Feb 26 '09 at 16:18
source share
4 answers

The problem is that setTimeout () forces javascript to use the global scope. Essentially, you are calling the method () class, but not from "this". Instead, you simply tell setTimeout to use the "method" function, without any specific scope.

To fix this, you can wrap a function call in another function call that references the correct variables. It will look something like this:

 test.protoype.method = function() { var that = this; //method2 returns image based on the id passed this.method2('useSomeElement').src = "http://www.some.url"; var callMethod = function() { that.method(); } timeDelay = window.setTimeout(callMethod, 5000); }; 

"which may be" this "because callMethod () is within scope.

This problem becomes more complicated when you need to pass parameters to the setTimeout method, since IE does not support more than two parameters for setTimeout. In this case, you will need to read closures .

In addition, as a side element, you are setting yourself up for an infinite loop, since the () method always calls the () method.

+36
Feb 26 '09 at 16:37
source share

A more elegant option is to add .bind(this) to the end of your function. For example:.

  setTimeout(function() { this.foo(); }.bind(this), 1000); // ^^^^^^^^^^^ <- fix context 

So the answer to the OP question could be:

  test.prototype.method = function() { //method2 returns image based on the id passed this.method2('useSomeElement').src = "http://www.some.url"; timeDelay = window.setTimeout(this.method.bind(this), 5000); // ^^^^^^^^^^^ <- fix context }; 
+37
Oct. 26 '13 at 17:41
source share

The "this" that you used in setTimeOut is looked through through itself. Create var "foo = this;" inside your function test.prototype.method and use foo instead.

+7
Feb 26 '09 at 16:36
source share

I get an error that says method2 is undefined

Yes, when you drop "this.method" from its owner and pass only the setTimeout function, you lose the association that sets this, so "this in method () is equal to the window of the global object."

See this answer for an explanation of the amazing way "this really works in JavaScript.

0
Feb 26 '09 at 16:40
source share



All Articles