Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When actually is a closure created?

Is it true that a closure is created in the following cases for foo, but not for bar?

Case 1:

<script type="text/javascript">

    function foo() { }

</script>

foo is a closure with a scope chain with only the global scope.

Case 2:

<script type="text/javascript">

    var i = 1;
    function foo() { return i; }

</script>

same as Case 1.

Case 3:

<script type="text/javascript">

    function Circle(r) {
        this.r = r;
    }
    Circle.prototype.foo = function() { return 3.1415 * this.r * this.r }

</script>

in this case, Circle.prototype.foo (which returns the circle's area) refers to a closure with only the global scope. (this closure is created).

Case 4:

<script type="text/javascript">

    function foo() { 
        function bar() { 
        }
    }

</script>

here, foo is a closure with only the global scope, but bar is not a closure (yet), because the function foo is not invoked in the code, so no closure bar is ever created. It will only exist if foo is invoked , and the closure bar will exist until foo returns, and the closure bar will then be garbage collected, since there is no reference to it at all anywhere.

So when the function doesn't exist, can't be invoked, can't be referenced, then the closure doesn't exist yet (never created yet). Only when the function can be invoked or can be referenced, then the closure is actually created?

like image 636
nonopolarity Avatar asked May 06 '10 10:05

nonopolarity


2 Answers

A closure is when free variables in some function code are bound to some values by the function "context" (closure being a more proper term here than context).

<script type="text/javascript">
    var i = 1;
    function foo() { return i; }
</script>

Here, i is a free variable for the function code of foo. And this free variable is not bound to any particular value by any existing context (closure). So you don't have any closure.

<script type="text/javascript">
    var i = 1;
    function foo() { return i; }
    foo(); // returns 1
    i = 2;
    foo(); // returns 2
</script>

Now to create a closure you have to provide a value-bounding context:

<script type="text/javascript">

    function bar() {
       var i = 1;
       function foo() { return i; }
       return foo;
    }
    bar(); // returns function foo() { return i; }
    bar()(); // returns 1
    // no way to change the value of the free variable i => bound => closure
</script>

In summary, you can't have a closure unless a function returns another function. In that case, the returned function has all the variable-value bindings that existed in the returning function when it exited.

<script type="text/javascript">

    function bar() {
       var i = 1;
       function foo() { return i; }
       i = 2;
       return foo;
    }
    bar()(); // returns 2
</script>

Concerning your exemples:

  1. Case 1 is not a closure, it's just a function
  2. Case 2 is not a closure, it's another function with a free variable
  3. Case 3 is not a closure, it's yet another function with the special "variable" this. When the function is called as member of an object, the object is assigned to the value of this. Otherwise, the value of this is the global object.
  4. Case 4 is not a closure, it's a function defined inside another function. Should foo return bar, you would create a closure that contains only 'bar' and its value : function bar() {}.
like image 128
Alsciende Avatar answered Oct 27 '22 03:10

Alsciende


closure bar will exist until foo returns, and the closure bar will then be garbage collected, since there is no reference to it at all anywhere

Yes.

like image 35
Delan Azabani Avatar answered Oct 27 '22 02:10

Delan Azabani