Good day! Recently, I studied JavaScript and сame across an interesting topic:
function closures. This feature available in many functional programming languages, but I would like to describe it on JavaScript language.
Let's start! Firstly, we need to get acquainted with the concept of global and local variables.
In JavaScript, global variables is a variable or function, which are not inside some function. In JavaScript, all global variables are the properties of the global object (for example, in the browser, the global object is
window. Example of global variable:
var a = 15;
The variables, which declared inside the function are called local. Every function has own special object, which contains all variables of function -
LexicalEnvironment object. When we create new function, we create new
LexicalEnvironment object also. Moreover, every
LexicalEnvironment object has a property [[Scope]], which contains a reference to an outer object LexicalEnvironment. As result, if we can't find a variable in the current LexicalEnvironment, we can find it in the outer LexicalEnvironment object. Let's review the example:
function outerFunc() {
var a = 5; //LexicalEnvironment = {..., a: 5};
(function innerFunction() {
//LexicalEnvironment of inner function not contains "a" variable
//Take the variable from outer LexicalEnvironment
console.log(a);
})();
}
outerFunc(); //Output - 5;
Now, let's review the definition of closures. According to Wikipedia,
"In programming languages, closures (also lexical closures or function closures) are techniques for implementing lexically scoped name binding in languages with first-class functions." AnothrWords, internal function remember the outer LexicalEnvironment and use the variables from there. Let's look at an example and discuss it:
function getCounter() {
var count = 0;
return function() {
return count++; //Usage of outer LexicalEnvironment
}
}
var counter1 = getCounter();
console.log(counter1()); //0
console.log(counter1()); //1
//...
//Counters are indepentent
var counter2 = getCounter();
console.log(counter2()); //0
console.log(counter2()); //1
In this example we can see, that inner function use outer variable
count and increment it. The result returned by the function call getCounter() refers to it's own outer LexicalEnvironment. When we invoke function getCounter(), we create new LexicalEnvironment and new variable count, as result, all counters are independent.
I hope, this article gave you knowledge about the concept of closure! If you have a questions, you can ask it in comments.