245

I am learning JavaScript and I have learned recently about JavaScript timing events. When I learned about setTimeout at W3Schools, I noticed a strange figure which I didn’t run into before. They are using double quotes and then call the function.

Example:

setTimeout("alertMsg()", 3000);

I know that double and single quotes in JavaScript means a string.

Also I saw that I can do the same like that:

setTimeout(alertMsg, 3000);

With the parentheses it’s referring, without the parentheses it’s copied. When I am using the quotes and the parentheses it’s getting crazy.

I will be glad if someone can explain to me the difference between these three ways of using setTimeout:

With the parentheses:

setTimeout("alertMsg()", 3000);

Without the quotes and the parentheses:

setTimeout(alertMsg, 3000);

And the third is only using quotes:

setTimeout("alertMsg", 3000);

N.B.: A better source for setTimeout reference would be MDN.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
user1316123
  • 2,519
  • 2
  • 14
  • 7
  • @Jefffrey Though I love stackoverflow but what's wrong with following w3cschools? – Faizan Nov 07 '13 at 13:58
  • 5
    @Jefffrey that w3fools website doesn't say that the content there is wrong, just that it might be outdated and missing some of the newer stuff. Should be fine to use as a reference for (or to learn) the core stuff. I can understand people being frustrated by the way they try to seem like they're part of w3, but that doesn't detract from the content. It's nicely laid out and easy to read with clear examples, prefect for noobs. – Matthew Nov 13 '13 at 18:48
  • 14
    @Matthew "We feel, though, that W3Schools is harming the community with inaccurate information." -- within the first three lines. – Shoe Nov 13 '13 at 20:14
  • 1
    @Jefffrey yeah I saw that but lower down where they explain what they don't like about it, in the "W3Schools is trouble" section, none of the three reasons they give have anything to do with inaccurate information. They don't have a single example of anything that is actually "wrong". Their complaints are that they don't explicitly say they aren't affiliated with w3, they charge for unrecognized certifications, and they don't update quickly with new content (e.g. html 5). – Matthew Nov 13 '13 at 21:31
  • 10
    @Matthew, Outdated informations, in delicate languages like Javascript, SQL or PHP, is what guides masses of aspiring programmers to stick to old and potentially dangerous technologies (such as the `mysql_` extension of PHP) of which the SO question stream is just an example. IIRC there were some very subtle mistakes in the SQL section as well, but it's been almost a year since the last time I've visited the website and a lot of them may as well be fixed. And even if all above was perfect I wouldn't still promote a website which tries to deceive people with their certificate's fraud. – Shoe Nov 14 '13 at 01:00
  • 4
    shady certifications aside, it's a decent reference resource and it's counterproductive to the whole point of SO to go around denouncing them. – worc Dec 03 '13 at 23:46
  • Single and double quotes can sometimes be interchanged, but keep them in pairs. If you specifically need either one then you can use the other for the next quote level inside that. – Alan Corey Apr 08 '18 at 17:55

7 Answers7

386

Using setInterval or setTimeout

You should pass a reference to a function as the first argument for setTimeout or setInterval. This reference may be in the form of:

  • An anonymous function

    setTimeout(function(){/* Look mah! No name! */},2000);
    
  • A name of an existing function

    function foo(){...}
    
    setTimeout(foo, 2000);
    
  • A variable that points to an existing function

    var foo = function(){...};
    
    setTimeout(foo, 2000);
    

    Do note that I set "variable in a function" separately from "function name". It's not apparent that variables and function names occupy the same namespace and can clobber each other.

Passing arguments

To call a function and pass parameters, you can call the function inside the callback assigned to the timer:

setTimeout(function(){
  foo(arg1, arg2, ...argN);
}, 1000);

There is another method to pass in arguments into the handler, however it's not cross-browser compatible.

setTimeout(foo, 2000, arg1, arg2, ...argN);

Callback context

By default, the context of the callback (the value of this inside the function called by the timer) when executed is the global object window. Should you want to change it, use bind.

setTimeout(function(){
  this === YOUR_CONTEXT; // true
}.bind(YOUR_CONTEXT), 2000);

Security

Although it's possible, you should not pass a string to setTimeout or setInterval. Passing a string makes setTimeout() or setInterval() use a functionality similar to eval() that executes strings as scripts, making arbitrary and potentially harmful script execution possible.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Joseph
  • 117,725
  • 30
  • 181
  • 234
  • i have learned that when you are using only the function name the function is copied so why are you saying at your first example that setTumeout foo (function) pass reference the function has i leaned is copied. and can you tall me more please about the eval please. – user1316123 Apr 25 '12 at 09:44
  • 42
    @user1316123 functions are never copied. same with objects and arrays. they are [passed by reference](http://snook.ca/archives/javascript/javascript_pass). you should stop reading w3schools. [they are doing more harm than good](http://w3fools.com/) – Joseph Apr 25 '12 at 09:47
  • 4
    @JosephtheDreamer functions _are_ objects. "A function name" and "A variable that refers to a function" is the _same_ thing. Also, you can pass parameters to setTimeout directly (no need to wrap in a lambda for it (although like you said - newer browsers). Also, the problem isn't with letting users execute scripts (they can always do this anyway), it's by accepting input from _other_ users and running _that_ as script. The user themselves can always just open the console and execute arbitrary JavaScript. – Benjamin Gruenbaum Jun 23 '13 at 19:38
  • @BenjaminGruenbaum I was about to make a nearly identical comment to your second sentence. Laugh :) – ErikE Jul 16 '13 at 20:24
  • 2
    I didn't realise you needed to use a function for setTimeout to work properly. Thanks for clearing that up. – Matt Dell Jul 24 '13 at 10:30
3

i think the setTimeout function that you write is not being run. if you use jquery, you can make it run correctly by doing this :

    function alertMsg() {
      //your func
    }

    $(document).ready(function() {
       setTimeout(alertMsg,3000); 
       // the function you called by setTimeout must not be a string.
    });
Fábio Batista
  • 25,002
  • 3
  • 56
  • 68
Acil Az
  • 170
  • 2
  • 9
  • i thinkink Just like you but the link http://www.w3schools.com/js/js_timing.asp saying somting else – user1316123 Apr 25 '12 at 09:48
  • if i understand Correctly when i using Brackets i can referring only to the function that contain the setTimeout method becouse the function Available at the brackets only at it local scope? – user1316123 Apr 25 '12 at 10:07
2

Totally agree with Joseph.

Here is a fiddle to test this: http://jsfiddle.net/nicocube/63s2s/

In the context of the fiddle, the string argument do not work, in my opinion because the function is not defined in the global scope.

Nicocube
  • 2,962
  • 2
  • 20
  • 28
  • http://www.w3schools.com/js/js_timing.asp if you can enter the link please and see becouse Joseph says its dangerous but if you enter the link its working – user1316123 Apr 25 '12 at 09:50
  • guys please look at this : http://www.quirksmode.org/js/this.html this link says that a func can be copied – user1316123 Apr 25 '12 at 09:53
  • Yes it can, because function are object in JS. The problem with eval is that it will eval in global context, and fail to get local context which occurs with a fiddle. – Nicocube Apr 25 '12 at 09:56
  • can you explain in some words about eval please. – user1316123 Apr 25 '12 at 10:01
  • Some good explanations: http://javascriptweblog.wordpress.com/2010/04/19/how-evil-is-eval/ – Nicocube Apr 25 '12 at 12:07
1

What happens in reality in case you pass string as a first parameter of function

setTimeout('string',number)

is value of first param got evaluated when it is time to run (after numberof miliseconds passed). Basically it is equal to

setTimeout(eval('string'), number)

This is

an alternative syntax that allows you to include a string instead of a function, which is compiled and executed when the timer expires. This syntax is not recommended for the same reasons that make using eval() a security risk.

So samples which you refer are not good samples, and may be given in different context or just simple typo.

If you invoke like this setTimeout(something, number), first parameter is not string, but pointer to a something called something. And again if something is string - then it will be evaluated. But if it is function, then function will be executed. jsbin sample

Vitaliy Markitanov
  • 2,205
  • 1
  • 24
  • 23
0
    ##If i want to wait for some response from server or any action we use setTimeOut.

    functionOne =function(){
    console.info("First");

    setTimeout(()=>{
    console.info("After timeOut 1");
    },5000);
    console.info("only setTimeOut() inside code waiting..");
    }

    functionTwo =function(){
    console.info("second");
    }
    functionOne();
    functionTwo();

## So here console.info("After timeOut 1"); will be executed after time elapsed.
Output:
******************************************************************************* 
First
only setTimeOut() inside code waiting..
second
undefined
After timeOut 1  // executed after time elapsed.
Avinash Khadsan
  • 441
  • 3
  • 6
0

For what it's worth, I found another quirk about the setTimeout function:

setTimeout(myFunction(),10000);    // executes immediately!!
setTimeout('myFunction()',10000);  // executes in 10 seconds
-1

With the parentheses:

setTimeout("alertMsg()", 3000); // It work, here it treat as a function

Without the quotes and the parentheses:

setTimeout(alertMsg, 3000); // It also work, here it treat as a function

And the third is only using quotes:

setTimeout("alertMsg", 3000); // It not work, here it treat as a string

function alertMsg1() {
        alert("message 1");
    }
    function alertMsg2() {
        alert("message 2");
    }
    function alertMsg3() {
        alert("message 3");
    }
    function alertMsg4() {
        alert("message 4");
    }

    // this work after 2 second
    setTimeout(alertMsg1, 2000);

    // This work immediately
    setTimeout(alertMsg2(), 4000);

    // this fail
    setTimeout('alertMsg3', 6000);

    // this work after 8second
    setTimeout('alertMsg4()', 8000);

In the above example first alertMsg2() function call immediately (we give the time out 4S but it don't bother) after that alertMsg1() (A time wait of 2 Second) then alertMsg4() (A time wait of 8 Second) but the alertMsg3() is not working because we place it within the quotes without parties so it is treated as a string.

Srikrushna
  • 4,366
  • 2
  • 39
  • 46
  • Demonstrates the scenarios the questioner asks about, but doesn't actually answer the question. I don't see what this adds over the existing ***6 year old*** answers. – Stephen P Apr 02 '19 at 18:34