-1

I am going through a book on Javascript and tried one of its example of closure.

function animateIt(id) {
   var elem= document.getElementById(id);
   var tick=0;

   var timer=setInterval(function() {
     if (tick<100) {

       elem.style.left = tick+"px";
       elem.style.top=tick+"px";
       tick++;
     } else {
       clearInterval(timer);
       assert(tick==100, "Tick Accessed and has value:- "+ tick);
       assert(elem, "element accessed");
       assert(timer, "timer accessed")
     }
   }, 10);
 }
 animateIt(box);      

but the function in timer doesn't have access to elem, tick etc. whereas the book says it should have access to the same. Please let me know.

Viktor Kukurba
  • 1,360
  • 9
  • 14
shubh
  • 9
  • 4
  • Where is `box` defined ? – guest271314 Feb 12 '16 at 18:16
  • 1
    _"doesn't have access to elem, tick etc"_ how do you know you do not have access to them? Are you getting errors on the console saying they do not exist? The only problem I see in the code is that it might be running before the element identified by `id` exists so `elem` would end up being `null` – Patrick Evans Feb 12 '16 at 18:19
  • 1
    [It works](https://jsfiddle.net/r2u5r8f9/) – Oriol Feb 12 '16 at 18:20
  • @Oriol Should `console.assert` be substituted for `assert` ? Also should first parameter passed to `assert` be a `Boolean` https://developer.mozilla.org/en-US/docs/Web/API/console/assert ? https://jsfiddle.net/r2u5r8f9/1/ – guest271314 Feb 12 '16 at 18:24
  • Similar question: [How do JavaScript closures work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) "Once upon a time there was a princess..." – Yogi Feb 12 '16 at 18:27
  • 1
    @guest271314 Yes, the call to `assert` throws, but that is not much relevant. I meant the animation works. – Oriol Feb 12 '16 at 18:32
  • Thanks @Oriol it works i made a stupid mistake while calling the function animateIt() – shubh Feb 13 '16 at 02:22

3 Answers3

0

This can be considered as closure, function animateIt contains variables id and elem, so if you will run animateIt for different ids it will work correctly.

Viktor Kukurba
  • 1,360
  • 9
  • 14
0

You didn't give the whole code(box, assert) but as it seems as there is closure. assuming that function animateIt is now executed, there is a new execution context created, along with vars such as tick and elem.

When the the execution reaches here:

var timer=setInterval(function() {

a new function is created. it is an anon function. it is the function inside setInterval, and it has a reference to it's parent function(animateIt) scope object. the scope object contains the vars - elem, tick. it has a reference to the scope object because function anon sits inside function animateIt, lexically. the parent itself contains vars such as

var elem= document.getElementById(id);
var tick=0;

these vars are referenced by your anon function(inside setInterval) because they are inside the scope object of animateIt, and your anon function has a reference to it.

once animateIt function execution context is over, the function which you passed to the event queue through setInterval keeps on executing itself on and off because of setInterval, and it has an access to the vars of a function which used to "exist"(during it's execution), but now doesn't. that function is called animateIt, and closure is what saved those vars(tick,elem) in memory.

RunningFromShia
  • 590
  • 6
  • 20
-1

The tick variable which is visible inside of a unnamed function call (setInterval contains unnamed function) is a closure.

Closure is created per function call.

//source function which contain the variable: 
//lets consider it as a global function call
var tick=0;

(function() {
    //target function
    //1. closure is created on function call and 
    //2. another characterictic of closure is that 
    // source function must be parent of the target function
    console.log(tick); //so closure is equal to implicit parametrization
    //on target function call
}());

In previous example I am calling a function an implicitly a variable is added an implicitly to inner "scope" on the target fucntion call.

I use another name for "closure" (implicit parametrization on function call).

function animateIt(id) {

    var timer=setTimeout(function() {
        id="wow"; //important! there is no var keyword, so the outer variable is changed
    }, 1000);

   var timer=setInterval(function() { //on each function call a closure is created
     // in your case a built in function calls the function and 
     // on each call a closure is created
     console.log(id)
   }, 10);

 }

 animateIt("test");
Anton Lyhin
  • 1,925
  • 2
  • 28
  • 34
  • 1
    No, a closure is created when a function definition is evaluated; capturing the lexical scope at the point of its definition. What you have there is a scope. – Dan D. Feb 12 '16 at 18:19
  • A new scope is created for each evaluation of the body of a function, in which the arguments and local variables are bound, as a result of a function call. – Dan D. Feb 12 '16 at 18:21
  • I thought that "scope" decribes better varibale storage in languages like c#, because the following expression { } definitely cleans inner variables (not-functional language). So I believe we should not use "scope" term in javascript, because closure is created on function call (this is functional language behaviour). As an example http://stackoverflow.com/a/111111/1145224 Example 7. What do you think, Dan? – Anton Lyhin Feb 12 '16 at 18:30
  • @DanD. , can you please referense the book or blog were your scope and closure definitions are mentioned? – Anton Lyhin Feb 12 '16 at 19:27
  • 1
    Well, [_lexical environment_](https://es5.github.io/#x10.2) is the term that the ES5 standard uses. – Dan D. Feb 13 '16 at 03:09
  • A lexical environment is a map from identifiers to locations that contain values. Where as a closure is a Function object which has two parts one a reference to the code that makes up the body of the function and a reference to the lexical environment in which the definition that created it occurred. See [Function Definition](https://es5.github.io/#x13) – Dan D. Feb 13 '16 at 03:14
  • But it does use `[[Scope]]` to refer to the property that functions have which is in fact the scope in which their definition occurred. – Dan D. Feb 13 '16 at 03:22