27

I have some JS code as below:

var x = self.someAJAXResponseJSON; // x has some object value here.

setTimeout(function(x){
  console.log("In setTimeout:", x); // But x is undefined here
}, 1000);

So I want to pass x to the setTimeout callback function. But I am getting x as undefined inside the setTimeout.

What am I doing wrong?

Any idea how to fix a similar issue using Dojo.js?

setTimeout(dojo.hitch(this, function(){
  this.executeSomeFunction(x); // What should this be?
  console.log("In setTimeout:", x); // But x is undefined here
}), 1000);
Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
copenndthagen
  • 49,230
  • 102
  • 290
  • 442
  • if `var x` is defined earlier, isn't this possible - > `setTimeout(function(){ console.log("setTimeout ... : " + x); }, 1000);`. Removing `x` from `callback` and assigning it directly? – Guruprasad J Rao Sep 01 '15 at 08:18
  • well, I think that the aim in this case should be like creating several functions with different _x_ values. Can you explain this a little bit more @testndtv? – pietro909 Sep 01 '15 at 08:22
  • Does this answer your question? [How can I pass a parameter to a setTimeout() callback?](https://stackoverflow.com/questions/1190642/how-can-i-pass-a-parameter-to-a-settimeout-callback) – Serge Stroobandt Apr 09 '21 at 08:50
  • Related: [Why is a global variable undefined inside a function when I call it?](/q/15309718/4642212). – Sebastian Simon Dec 05 '22 at 08:32

6 Answers6

31

Alternatively you can do it without creating a closure.

function myFunction(str1, str2) {
  alert(str1); //hello
  alert(str2); //world
}

window.setTimeout(myFunction, 10, 'hello', 'world');

But note it doesn't work on IE < 10 according to MDN.

Purag
  • 16,941
  • 4
  • 54
  • 75
Maciej Krawczyk
  • 14,825
  • 5
  • 55
  • 67
15

When setTimeout invokes the callback, it doesn't pass any arguments (by default); that is, the argument x is undefined when the callback is invoked.

If you remove the parameter x, x in the function body won't refer to the undefined parameter but instead to the variable you defined outside the call to setTimeout().

var x = "hello";
setTimeout(function () { //note: no 'x' parameter
    console.log("setTimeout ... : " + x);
}, 1000);

Alternatively, if it must be a parameter, you can pass it as an argument to setTimeout (do yourself a favor and name it differently, though):

var x = "hello";
setTimeout(function (y) {
    console.log("setTimeout ... : " + y);
}, 1000, x);
Purag
  • 16,941
  • 4
  • 54
  • 75
6

Ran into this myself and looked at the Node docs, arguments to be passed into the function come in as a 3rd(or more) parameter to the setTimeout call so...

myfunc = function(x){console.log(x)};
x = "test";
setTimeout(myfunc,100,x);

Worked for me.

2

In your code, console.log(x)refers to the x parameter of the callback function.

Just omit it from function signature, and you'll be fine:

setTimeout(function(){
  console.log("setTimeout ... : " + x); // now x is the global x
}, 1000);
moonwave99
  • 21,957
  • 3
  • 43
  • 64
2

It is because the function is called without passing it any argument: so x is undefined.

You should wrap it in a closure if you are willing to call it with different parameters for x:

var x = self.someAJAXResponseJSON; // x has some object value here
setTimeout((function(y){
    return(function() {
        console.log("setTimeout ... : " + y);
    })
})(x), 1000);
pietro909
  • 1,811
  • 1
  • 19
  • 26
  • 1
    it's not exactly that "the function is called from a different scope." The function opens a new scope, and that scope has an identifier `x` defined in it, which is undefined by default. – Purag Sep 01 '15 at 08:25
  • You also don't *need* a different name. It will have no effect. – Purag Sep 01 '15 at 08:26
  • It was just for making it better understood: I'm supposing that he doesn't have a clear understanding of how scopes work. – pietro909 Sep 01 '15 at 08:27
  • 1
    I would rather do `setTimeout((function(x){ ... }).bind(null, x), 1000)` then : )) – moonwave99 Sep 01 '15 at 08:36
  • @pietro909 you should include the `bind` method in your answer. :) – Purag Sep 01 '15 at 09:01
0

setTimeout method is designed to take function or code snippet as its first argument but in you case you have taken an anonymous function with parameter x and which is called without taking any argument so it shows is undefined because there is no concrete function defined that takes x. What you can do is you can first define the function you want to call and then just call it in setTimeout method. See following code snippet:

var x = self.someAJAXResponseJSON;
function mylog(x){
  console.log("setTimeout ... : " + x);
}
setTimeOut(mylog(x),1000);
Rahul Singh
  • 892
  • 9
  • 24