4

I've just started learning about closures in JS, and someone told me that I actually have written closures without realizing they were closures. I thought this was just a singleton object/class, but he thinks this is a closure:

var myWidget = {
    counter : 0,
    init : function() {
        myWidget.left();
        myWidget.right();
    },
    left : function() {
        // whatever
    },
    right : function() {
        // whatever
    }
}
myWidget.init();

Is this a closure? If not, what is it?

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
drumwolf
  • 399
  • 1
  • 4
  • 16
  • Well, I think technically every function in JS is a closure as it _will_ capture the state of the surrounding environment. I may be wrong though. – Dogbert May 08 '13 at 05:39
  • This [link](http://stackoverflow.com/q/111102/1577396) might help you to understand closures clearly. – Mr_Green May 08 '13 at 05:49
  • This is neither a class nor a closure. Selected answer in wrong. – Beetroot-Beetroot May 09 '13 at 00:06
  • Hi Mr @Beetroot-Beetroot, no class there but definately a closure. I would hate to have been wrong all this time, please can you try and enlighten me with a more detailed answer. – Steven de Salas Jun 16 '15 at 00:52

4 Answers4

3

Yup, it does.

In that code sample you are:

  1. Defining a plain object with some properties
  2. Using a closure inside one of the properties (a function) to refer to the object you just defined.

I can see that whether you are defining var myWidget in global scope or inside another function, you will still be traversing up the scope chain to get a reference to myWidget.

If we use this definition of closures here:

A closure is a combination of a code block and data of 
a context in which this code block is created.

Or the mozilla definition:

Closures are functions that refer to independent (free) variables. In other words, 
the function defined in the closure 'remembers' the environment in which it was created.

When executing the code block inside myWidget.init() you are using a closure to refer to myWidget in the calls to myWidget.left() and myWidget.right() as you carry the myWidget variable in your context/environment (as opposed to finding it locally within the init() function).

In other words, when you execute myWidget.init() the following happens:

  1. Is myWidget a local variable inside the current function() ? NO
  2. Move up to parent scope (ie GLOBAL)
  3. Is myWidget a variable in current (ie GLOBAL) scope? YES --> CLOSURE USAGE
  4. Ok use this myWidget reference to retrieve the variable.

I hadn't ever thought of closures in global scope but it makes perfect sense that scope chaining keeps travelling all the way to up to GLOBAL, which just acts as another function() {} code block which wraps everything and is the ultimate source for finding the variable we are after, here is another article that supports this view:

http://lostechies.com/derickbailey/2011/11/30/is-javascripts-global-scope-really-just-a-closure/

Steven de Salas
  • 20,944
  • 9
  • 74
  • 82
  • Interesting Steven, I hadn't realized `myWidget.right()` would be creating a closure to the previously defined `myWidget`, a bit quirky IMO, but a closure nonetheless! – quickshiftin May 08 '13 at 06:28
  • The closure is created inside `myWidget.init()`, thats the code block containing the previously-defined variable `myWidget`. `myWidget.left()` is just the bit of data we are referencing. Closures are a bit like debt, you can keep borrowing up the chain all the way up to the central bank. – Steven de Salas May 08 '13 at 06:31
  • So exactly what part is the "closure"? If I'm understanding correctly, it sounds like "myWidget" is not a closure in and of itself, but executing "myWidget.init()" IS the closure? – drumwolf May 08 '13 at 17:41
  • I would not consider the act of creating functions in the *global* context which use *global* variables to be a closure. To my understanding, it should be a local scope that is closed over, since you have explicit control over that. – Bergi May 09 '13 at 00:03
  • The use of variable `myWidget` inside `myWidget.init()` is a closure because that variable cannot be found inside the function `init()`, and is found instead by looking into the context where the function was created (ie a few lines above but outside the `function() {}` code block). Closure is the **act of looking into a parent context** for your variable (and finding it there). – Steven de Salas May 09 '13 at 00:04
  • Not by [formal defintion](http://en.wikipedia.org/wiki/Closure_(computer_science)). What you are describing is just a lookup in the scope chain. The point of using closures is that the context which the function uses for looking up its variables *is not accessible* to the caller of that function – Bergi May 09 '13 at 00:07
  • To put in into layman terms: if you are *Mr Init()* and you are told you need to use a widget for a particular job, but you dont **have** one and have to ask your boss for it (your boss is the parent context) and maybe he has to ask his boss and so on all the way to the CEO, then you'll be using a closure if you find your widget (at any level of the organization). – Steven de Salas May 09 '13 at 00:07
  • No. I'm a closure if my friend wants to borrow a widget which I can acquire from my boss (or the CEO), while my friend could not get it from them (e.g. cause he doesn't know them, or works elsewhere) – Bergi May 09 '13 at 00:10
  • Hi @Bergi, I agree this is how you may want to use a closure, but its not what the closure is of itself. As per the wikipedia link, the closure is the **ability to reference the environment of the function** (that is being called). – Steven de Salas May 09 '13 at 00:22
  • 1
    I think [this section from the article you linked](http://dmitrysoshnikov.com/ecmascript/chapter-6-closures/#theory-versions) explains it best. Theoretically, all JS functions are closures, but from the practical viewpoint we call only those function "closures" which *make use* of it (which is not the case here) :-) – Bergi May 09 '13 at 00:27
  • Nice, Bergi sort of strengthens the case I made in my answer. Frankly, I've not read up much on the formal definition, but at this point I'm going to make a plan of it! – quickshiftin May 09 '13 at 03:39
2

It doesn't look like a closure to me. Here would be a better example.

function init() {
    var counter = 0;

    return {
        inc: function() {
            counter++;
        },
        show: function() {
            return counter;
        }
    }
}

The closure is around the counter variable here. The reason is when you say

var thing = init();

Javascript has to keep a reference to what would normally have been a local variable to the init function and hence destroyed after its execution. With this setup, functions that can manipulate that local variable have been returned.

Try calling

thing.inc();
alert(thing.show());
thing.inc();
alert(thing.show());

You will see 1 and then 2 in the alerts, but remember, that's a local variable to init you're manipulating! That's a closure.

Edit

Having read around a bit, it's clear that the code in question does have a closure. The thread I most enjoyed on the topic was here. As it turns out, what I have in my answer is one particular example of a closure, but by no means the only one.

Community
  • 1
  • 1
quickshiftin
  • 66,362
  • 10
  • 68
  • 89
  • This is a good example of how to use closures to mimic `private` properties in classic OO languages such as C# and Java. However the code in the question also qualifies as a closure. – Steven de Salas May 09 '13 at 23:47
  • @StevendeSalas yup, totally realized that after reading around last night. – quickshiftin May 10 '13 at 00:07
0

No closure is created in this case. Refer to this How do JavaScript closures work?

accessing variables outside of your immediate lexical scope creates a closure

myWidget is defined in the global scope, so a closure is not generated for init when it accesses myWidget.

If you defined myWidget inside a function, and in init accessed variables in the outer function's scope, then a closure will be generated.

var myWidget = (function() {
  var number = 1;

  return {
    counter : 0,
    init : function() {
      myWidget.left();
      myWidget.right();
      number++;
    },
    left : function() {
        // whatever
    },
    right : function() {
        // whatever
    }
  }
})();

myWidget.init();

when you call init with the above code, a closure is created containing the variable number

Community
  • 1
  • 1
-3
For implementing javascript closure you have to get plugin that will take care of all closure properties like css closure and javascript closure.

and you have to implement closure like the following example 

<g:compress>
  <link rel="stylesheet" type="text/css" href="css/dp.css"/>
  <link rel="stylesheet" type="text/css" href="css/demo.css"/>    
</g:compress>
...
<div id="datepicker"></div>
<g:compress>
  <script type="text/javascript" src="common.js"/>
  <script type="text/javascript" src="closure/goog/base.js"/>
  <script>
       goog.require('goog.dom');
       goog.require('goog.date');
       goog.require('goog.ui.DatePicker');
  </script>
  <script type="text/javascript">
      var dp = new goog.ui.DatePicker();
      dp.render(document.getElementById('datepicker'));
  </script>
</g:compress>