Hey i came across this video on youtube http://www.youtube.com/watch?v=KRm-h6vcpxs
which basically explains IIFEs and closures. But what I am not understanding is whether i need to return a function in order to call it a closure.
E.x.
function a() {
var i = 10;
function b() {
alert(i);
}
}
in this case can i call it a closure as it is accessing the 'i' variable from the outer function's scope or do i need to return the function like this
return function b(){alert(i);}
A closure is simply a function which holds its lexical environment and doesn't let it go until it itself dies.
Think of a closure as Uncle Scrooge:
Uncle Scrooge is a miser. He will never let go of his money.
Similarly a closure is also a miser. It will not let go of its variables until it dies itself.
For example:
function getCounter() {
var count = 0;
return function counter() {
return ++count;
};
}
var counter = getCounter();
See that function counter
? The one returned by the getCounter
function? That function is a miser. It will not let go of the count
variable even though the count
variable belongs to the getCounter
function call and that function call has ended. Hence we call counter
a closure.
See every function call may create variables. For example a call to the getCounter
function creates a variable count
. Now this variable count
usually dies when the getCounter
function ends.
However the counter
function (which can access the count
variable) doesn't allow it to die when the call to getCounter
ends. This is because the counter
function needs count
. Hence it will only allow count
to die after it dies itself.
Now the really interesting thing to notice here is that counter
is born inside the call to getCounter
. Hence even counter
should die when the call to getCounter
ends - but it doesn't. It lives on even after the call to getCounter
ends because it escapes the scope (lifetime) of getCounter
.
There are many ways in which counter
can escape the scope of getCounter
. The most common way is for getCounter
to simply return counter
. However there are many more ways. For example:
var counter;
function setCounter() {
var count = 0;
counter = function counter() {
return ++count;
};
}
setCounter();
Here the sister function of getCounter
(which is aptly called setCounter
) assigns a new counter
function to the global counter
variable. Hence the inner counter
function escapes the scope of setCounter
to become a closure.
Actually in JavaScript every function is a closure. However we don't realize this until we deal with functions which escape the scope of a parent function and keep some variable belonging to the parent function alive even after the call to the parent function ends.
For more information read this answer: https://stackoverflow.com/a/12931785/783743
Returning the function changes nothing, what's important is creating it and calling it. That makes the closure, that is a link from the internal function to the scope where it was created (you can see it, in practice, as a pointer. It has the same effect of preventing the garbaging of the outer scope, for example).
By definition of closure, the link from the function to its containing scope is enough. So basically creating the function makes it a closure, since that is where the link is created in JavaScript :-)
Yet, for utilizing this feature we do call the function from a different scope than what it was defined in - that's what the term "use a closure" in practise refers to. This can both be a lower or a higher scope - and the function does not necessarily need to be return
ed from the function where it was defined in.
Some examples:
var x = null;
function a() {
var i = "from a";
function b() {
alert(i); // reference to variable from a's scope
}
function c() {
var i = "c";
// use from lower scope
b(); // "from a" - not "c"
}
c();
// export by argument passing
[0].forEach(b); // "from a";
// export by assigning to variable in higher scope
x = b;
// export by returning
return b;
}
var y = a();
x(); // "from a"
y(); // "from a"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With