Calling the setTimeout Function recursively and passing an anonymous function

I am confused on the difference between this syntax:

var timerId;
 function clockStart(){
    // debugger;
    if(timerId){
      return;
    }
    update();
    // THIS LINE BELOW *********************************************
    var timerId = setTimeout(function(){clockStart()}, 1000);
  }
    function clockStop(){
      timerId = null;
    }
    function update(){
      var date = new Date();
      var hours = date.getHours();
      var minutes = date.getMinutes();
      var seconds = date.getSeconds();
      if(hours < 10) {
        hours = '0'+hours;
      }
      document.getElementById('hour').innerHTML = hours;
      if(minutes < 10){
        minutes = 0+minutes;
      }
      document.getElementById('min').innerHTML = minutes;
      if(seconds < 10){
          seconds = '0' + seconds;
      }
      document.getElementById('sec').innerHTML = seconds;
    }

I provided both functions being called but the main part of this function I do not understand is why I need to pass an anonymous function to call my clockStart() function.

My function works when I use this syntax:

    var timerId = setTimeout(function(){clockStart()}, 1000);

But it doesn’t work when I use:

    var timerId = setTimeout(clockStart(), 1000);

I have been working a while on these two functions and I honestly stumbled upon this by accident. I really don’t see what the anonymous function is doing besides invoking my clockStart function. But in my opinion, my clockStart() function should be invoked every second(1000ms) since it is calling itself, so why does it need an anonymous function to invoke it? Shouldn’t it be invoking itself?

If you would like to see this digital ‘clock’s’ full code please checkout my codepen link.

Answer

This line:

var timerId = setTimeout(clockStart(), 1000);

is calling clockStart() immediately and passing the return result from that function to setTimeout(). Since the function doesn’t return anything, you’re effectively doing this:

clockStart();
var timerId = setTimeout(undefined, 1000);

which obviously doesn’t do what you want.


You can use this instead:

var timerId = setTimeout(clockStart, 1000);

In this case, you want to pass a function reference to setTimeout() which means you do not include the parens. When you include the parens, that means to execute it NOW. When you just pass the name of the function, that is just a reference to the function (think of it like a handle) by which setTimeout() can call it later. That’s what you want.

When you do this:

var timerId = setTimeout(function(){clockStart()}, 1000)

you’re just defining an anonymous function and passing a reference to that anonymous function to to setTimeout() which works fine, but is not necessary in this case since you can just pass the clockStart name as in my third code example above.


Since you asked about how a function can call something later, I’ll show you a simple example. Here’s a function that takes a starting value, an ending value, an increment and a callback function. This will call the callback and pass it the value that it’s incrementing until the value exceeds the end value.

// define an increment function that will call a callback
// multiple times based on the start, end and increment arguments
function eachIncrement(start, end, increment, callback) {
    // the function argument named callback contains
    // a function reference
    var val = start;
    while (val <= end) {
        // execute the function reference and 
        // pass it the current val
        callback(val);
        val += increment;
    }
}

// define a function that we want to be called later
function processValues(num) {
    // this will get called multiple times with 
    // values 1, 4, 7, 10
}

// set up the increment parameters and pass a function reference
eachIncrement(1, 10, 3, processValues);

Leave a Reply

Your email address will not be published. Required fields are marked *