0

This is probably a noob question. The following code works just like I want it but I don't know why.

var x = 0

init_page = function(){
    x++;


    var y = x;

    setTimeout(go, 1000);
    function go(){
        $('body').append('<div>Y: '+y+'</div>');
    }

}
init_page();

Demo

If you click the link fast a few times it will print 1,2,3,4...

My issue is that they all call the same function but it acts as if the function has been instanced like this:

    function go1(){
        $('body').append('<div>Y: 1</div>');
    }
    function go2(){
        $('body').append('<div>Y: 2</div>');
    }
    function go3(){
        $('body').append('<div>Y: 3</div>');
    }

Shouldn't they all print the same number at the time of execution (the largest number) instead of the number at the time of clicking? I'd expect to see 4,4,4,4 because go() is the same function for all intervals.

Miro
  • 8,402
  • 3
  • 34
  • 72

3 Answers3

1

Since go is contained within init_page(), each time you queue up a new one, it's getting a different instance of the function defined. Each one of those also has it's own y variable, as declared in init_page, which will have the value that was assigned to it from the current value of x at the time init_page was called - that's why you're seeing the behaviour you are.

James Thorpe
  • 31,411
  • 5
  • 72
  • 93
1

You're declaring a local variable, y, which is bundled along with the scope of your inline function go. The variable y is initialized to the value of x - but since it's a primitive (pass by value, not reference) changes to either y or x will not impact each other.

If you moved y outside of your init_page this behavior would change.

bvaughn
  • 13,300
  • 45
  • 46
1

That sort of technique is called "Closure" in Javascript. When an inner function can access the scope of the outer function and preserves the outer scope for particular call. That is actually happening in your code when "go" function is being executed by "setTimeout" - it preserves the outer scope state of "init_page" function per each call.

Closures one of the powerful feature in javascript you can take a look at the following examples that you can achieve by using them:

  1. Encapsulation - make your function members private (accessible only inside of your function(object) scope).
  2. To preserve the outer scope state while working with asyncronous calls inside of the loop. (In your case setTimeout)

Here you can find some detailed answer as well: How do JavaScript closures work?

Community
  • 1
  • 1
Yuriy Anisimov
  • 825
  • 1
  • 7
  • 16