Reputation: 409
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
Reputation: 21467
Yup, it does.
In that code sample you are:
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:
myWidget
a local variable inside the current function()
? NOmyWidget
a variable in current (ie GLOBAL) scope? YES --> CLOSURE USAGEmyWidget
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
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
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
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