-1

I am trying to set a delay in the for loop in javascript. I want it to log i, have a delay, then log i, and so on. My question is, why does the following code work, having a function return a function as can be seen below:

for (var i = 1; i <= 5; i++) {
        var tick = function(i) {
            return function() {
                console.log(i);
            }
        };
        setTimeout(tick(i), 500 * i);
    }

And the following code not work as expected:

for (var i = 1; i <= 5; i++) {
    var tick = function(i) {
        return console.log(i);

    };
    setTimeout(tick(i), 500 * i);
}

It prints out all the values in the for loop at once. Could someone please explain why this happens?

ameenshake
  • 11
  • 1
  • 2
    first argument to setTimeout needs to be a function, not the result of calling a function, unless, as in the first case, the result of calling a function is a function itself – Jaromanda X Dec 20 '16 at 00:06
  • switch `var` to `let` – Endless Dec 20 '16 at 00:06
  • @Endless - no difference, as the second code example will try to call `undefined` after the timeout – Jaromanda X Dec 20 '16 at 00:06
  • 1
    @Endless - I disagree about the duplicate - as the code fails in the second example due to the misunderstanding of setTimeout more than closures – Jaromanda X Dec 20 '16 at 00:09
  • The issue with the second code block is explained [here](http://stackoverflow.com/q/8058996/5743988). – 4castle Dec 20 '16 at 00:11
  • 1
    @JaromandaX Ssh, I wanted the question to be closed in order to reopen and win a hat. Oh, well, closing to the appropriate target. – Oriol Dec 20 '16 at 00:11
  • Hat's have slowed SO down so much!!! I hate hats, but insist on wearing them :p – Jaromanda X Dec 20 '16 at 00:12
  • You need to understand closures and the way they work. If you want to print 1 to 5 then you need to write `for (var i = 1; i <= 5; i++) { (function(x) { setTimeout(function() { console.log(x); }, x * 1000 ); })(i); }` //prints 0 , 1 ,2, 3, 4, 5 – TechnoCorner Dec 20 '16 at 00:13
  • `var tick = function(i) { return function() { console.log(i); } };` `tick(i)` is the inner function returned, right? This is called a **closure**, which keeps having its environment. [`A closure is a function having access to the parent scope, even after the parent function has closed.`](http://www.w3schools.com/js/js_function_closures.asp) Thus each of the inner functions has a different value for _i_. That's why the inner functions can log _i_ of the time when they're generated even though it is called later. + I upvoted. :) – Константин Ван Dec 20 '16 at 00:17

1 Answers1

3

In both pieces of code, tick(i) is executed immediately in each loop

The difference is, that in the first example, tick(i) returns a function, which is called by setTimeout, and that outputs to the console

In the second example, the console.log is called immediately, undefined is returned, and setTimeout does nothing once the timeout has triggered as the given argument is not a function (or a string to be eval'd)

Jaromanda X
  • 53,868
  • 5
  • 73
  • 87