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?


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:

  • Case 1 is not a closure, it's just a function
  • Case 2 is not a closure, it's another function with a free variable
  • 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.
  • 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() {} .

  • 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.


    In none of these examples is a closure created.

    The second would create a closure if you actually created a function and did something with it, now you just create a function and then throw it away. Same as adding a line 3+8; , you create a number, and then throw it away.

    A closure is simply a function which references variables from its creation environment in its body, a canonical example is an adder:

    function createAdder(x) { //this is not a closure
        return function(y) { //this function is the closure however, it closes over the x.
            return y + x;
        }
    } //thus createAdder returns a closure, it's closed over the argument we put into createAdder
    
    var addTwo = createAdder(2);
    
    addTwo(3); //3
    
    链接地址: http://www.djcxy.com/p/51592.html

    上一篇: 这意味着全球命名空间会受到什么污染?

    下一篇: 实际上是否创建了一个闭包?