Closure seems like a buzz-word. In this article I’ll try to let you understand it in 3 minutes. I won’t tell you the definition of Closure at the beginning, as I think the best way to understand a new concept is to guess it.
Let me give you a simple example:
function outer() {
var i = 0;
return function inner() {
i++;
console.log("i=" + i);
};
}
var a = outer();
a(); //would print "1"
a(); //would print "2"
a(); //would print "3"
This is a closure! Can you guess what is a Closure?
You may say, that’s easy, returning a function inside a function means a closure. NO! That’s far from the actual meaning.
Let me give you a hint, the most important guy here is the variable “i”, without “i” there would be no closure.
If you look at it in detail, you probably discover that the variable “i” is declared in outer(), but used in inner(). There would be a big problem: when inner() is executed (on the lines with a();), “i” should be gone as outer() has finished the execution on the line above. So would it throw an error?
No, it won’t. The inner() function did reference “i” successfully (just try it out yourself if you want) and print “1”, “2” and “3” for the last 3 lines.
This is how Javascript handle “i”: When the outer() function finishes, normally Javascript would throw away “i” as “i” is the local variable, however this time someone (inner() function) keep a reference to “i”, so let’s not throw away “i” so that inner() can use it later.
Who can access “i”: only the inner() function. How about accessing “i” through “outer().i”? No you can’t do that.
CLOSURE ALERT! “i” is kept safely in a closed environment that only inner() can access it! That’s why it’s called a “closure”!
Now you think you know what’s a closure. Let’s play a game: I’ll give you some code and you tell me what is a closure:
var iGlobal = 0;
function outerGlobal() {
return function innerGlobal() {
iGlobal++;
console.log("iGlobal=" + iGlobal);
};
}
var aGlobal() = outerGlobal();
aGlobal(); //would print "1"
aGlobal(); //would print "2"
aGlobal(); //would print "3"
Closure or NOT?
You may think it’s a closure as it’s very similar to our closure example. Almost the same. even the output is the same.
However, the answer is NO, not a closure. Why? there were not any variables to close. i.e. iGlobal wasn’t in an closed environment. You can access iGlobal anywhere as it’s a global variable. At this point you may not understand me. You may say, what’s the point of keeping something in a closed environment?
If you run the following code, you would see why:
a = outer();
a(); //print "1"
a(); //print "2"
a(); //print "3"
var b = outer();
b(); //print "1"
b(); //print "2"
a = outerGlobal();
a(); //print "1"
a(); //print "2"
a(); //print "3"
b = outerGlobal();
b(); //print "4" ****
b(); //print "5" ****
Hint: You should see outer() as a counter function, as it outputs 1,2,3 which is counting.
You see the difference? even though “b” should be a different counter than “a”. When using outerGlobal(), “a” and “b” just shared the same counter value. When using outer(), “a” and “b” can be two different counters each having its own counter value.
Now you know that closure is about some variables used specific to a function call (e.g. outer()). Didn’t that sound familiar? In Object-oriented programming, there are some variables used specific to class instance (e.g. new Square()).
Well you’re right. In my point of view, closure are just like class. e.g. The following function (closure) and class are performing the same function:
class Square {
constructor(length) {
this.length = length;
}
area() {
return this.length * this.length;
}
}
var s = new Square(5);
console.log(s.area());
function Square2(length) {
return {
area: function () {
return length * length;
},
};
}
var s2 = new Square2(5);
console.log(s2.area());
There are examples of closure other than using it like a class. But once you understand this, you would understand all other cases.