Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript closure problem please explain

Tags:

javascript

This is a function taken from Pro JavaScript techniques that I'm trying to understand, but don't. The purpose of the function is to slowly reveal a hidden element by increasing its height over a matter of one second. The comments in the code are provided by the author of the book. I don't understand anything starting from where the author says in a comment "a closure to make sure we have the right 'i'.

Could you please explain in as much detail as possible

a) how does this closure work in this function. I.e. how does it make sure that it has the right 'i' and what in the code makes that important.

b) why is there a comma near the end of the program after elem in the code elem,.style.height

c) what is the purpose of this part of the code ( pos + 1) * 10). How does it work with the setTimeout function?

function slideDown(elem) {
  //start the slide down at 0
  elem.style.height = '0px';

    //Show the element, but can`t see it because height is 0
   show(elem);

    //find the full potential height of the element
    var h = fullHeight(elem);

   //We`re going to do a 20 frame animation that takes place over one second
   for (var i = 0; i <= 100; i +=5 ) {
         //a closure to make sure that we have the right 'i'
         (function() {
           var pos = i;

          //set the timeout to occur at the specified time in the future
          setTimeout(function() {

            //set the new height of the element
             elem,.style.height = (pos/100) * h) + "px";

         }, ( pos + 1) * 10);
       })();
     }
}
like image 915
mjmitche Avatar asked Nov 28 '25 03:11

mjmitche


2 Answers

a) This is essential because of the setTimeout() call. Since setTimeout() is, logically, a sleeping thread, it could be called after the next loop iteration, i could be a different value by the time the body of setTimeout() is invoked. "Saving" the i as pos fixes this potential issue, and protects the value of i in case it is changed in the meantime. Now, the value of pos is completely determined in advanced and is not subject to being changed by the main thread (the loop that is incrementing i).

b) No idea, looks like a typo. Edit: yes it is a typo. There you go.

c) It ensures that the body of setTimeout is called at a future time proportional to the value of i. Think about it; if every call was setTimeout(..., 10), then everything would start in 10ms but still be executed at whatever speed the loop was executed at. Adding pos as a factor in this value "slows down" the execution of the future setTimeout calls. As in the comments, it ensures that the future setTimeout() invocations occur at a rate of 20 times per second (creating a 20FPS animation effect)

like image 101
Travis Webb Avatar answered Nov 29 '25 17:11

Travis Webb


a) as you're iterating over i, and it pretends to be used in a callback, when the callback is called, the value of i will be the last i reached. Creating a closure, you create a copy of i (because it's a primitive type), with another position in memory. Doing this, when the callback is called, it will use the closure's instance.

The difference is that, in memory, you have only one i, but N instances of pos (and N closure scopes), so when the setTimeout callback starts, it will be referencing to the specific scope of the closure used to define it.

b) Sounds like a typo.

c) It's the time in milliseconds of delay. In the algorithm, it seems like it will fire the resize of the first element at 10 miliseconds, the second one at 20, and so on.

This functions works as this: setTimeout(callback, milliseconds), and a function could be anonymous, so setTimeout(function() { ... }, 10)is a valid syntax.

Good luck!

like image 26
Gonzalo Larralde Avatar answered Nov 29 '25 17:11

Gonzalo Larralde