drumwolf
drumwolf

Reputation: 409

Does this qualify as a Javascript closure?

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?

Upvotes: 4

Views: 178

Answers (4)

Steven de Salas
Steven de Salas

Reputation: 21467

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/

Upvotes: 3

quickshiftin
quickshiftin

Reputation: 69581

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.

Upvotes: 2

Kevin Deng
Kevin Deng

Reputation: 41

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

Upvotes: 0

VenkateshKumar
VenkateshKumar

Reputation: 96

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>

Upvotes: -3

Related Questions