17

How come I can say:

var myFunction = function() {
   setTimeout(myFunction, 1000);
}
myFunction();

Why does the function call in the setTimeout not require parentheses, but the last line does?

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
Phillip Senn
  • 46,771
  • 90
  • 257
  • 373

5 Answers5

22

Nutshell

  • myFunction references the function
  • myFunction() calls the function

More Words

setTimeout expects a function reference* as an argument.

There are circumstances where setTimeout(myFunction(), 1000) might make sense, like if myFunction() returns a function, e.g.

function myFunction() {
    return function() {
        alert("ohai")
    }
}

// Or

const myFunction = () => () => alert("ohai")

So:

setTimeout(myFunction(), 1000);
  • setTimeout gets the return value of myFunction
  • myFunction returns a function (that calls alert)

meaning there will be an alert every second.

See also Why function statement requires a name?

* Or a string to be evaluated, but a reference is preferred.

Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • 3
    Weird. JavaScript is a quirky language. – Phillip Senn Nov 01 '11 at 15:55
  • 3
    @cf_PhillipSenn: It is basically the same in Python or C (function pointers). Only providing the name of the function references it. Adding parenthesis behind it calls it. Of course this does not exist in languages where functions are not first class objects and therefore cannot be referenced directly (such as Java). – Felix Kling Nov 01 '11 at 15:57
  • 2
    It's not that weird :) you can do that sort of thing in C#, VB.NET too. It's a very useful feature. – M3NTA7 Nov 01 '11 at 16:05
11

myFunction is a function

myFunction() calls the function and yields whatever value the function returns.

The purpose of setTimeout is running code after some time elapses. You need to pass just the function to it (so setTimeout can itself call the function when appropriate) because if you called the function (with the parenthesis) before passing it to setTimeout it would execute now instead of after 1 second.

hugomg
  • 68,213
  • 24
  • 160
  • 246
7

When you use the parenthesis, it's saying 'call this function now'. So if you say setTimeout(myFunction(),1000);, it will use the return value of the function as the callback for the timeout. If the return value for the function is not itself a function, you'll get an error because it will try to execute something that isn't executable after the timeout (a string, a number, undefined, etc).

Chris
  • 1,040
  • 2
  • 14
  • 23
  • Although, worth noting: If the string that was returned was something that was executable, like say `alert("Hello world!");` it would work in this context because `setTimeout` can accept strings as js code literals. – Chris Nov 01 '11 at 16:06
2

In line 2, the function myFunction is not called, but passed as an argument to the setTimeout function, whereas in line 4 myFunction is called; to call a function, you always have to use parentheses, even if there are no arguments.

Luc125
  • 5,752
  • 34
  • 35
1

I think this example would make it clearer if i may,

function callback() {
  console.log('this function runs on page loads.');
}

setTimeout(callback(), 2000); 

Here callback() function will run immediately after page loads and won't wait 2 seconds.

function callback() {
  console.log('this function runs after page loads.');
}

setTimeout(callback, 2000);

Here callback() function will run after 2 seconds.

Safwat Fathi
  • 758
  • 9
  • 16