Closure – a construction when the function created in a certain field of visibility preserves its lexical environment even in in the case when it is not performed in its field of view.
The closure consists of 3 components:
- outer function – defines some scope and in which some variables are defined – lexical environment
- lexical environment – variables created in external functions
- nested function – a function that uses a lexical environment
function externalfunction() { //outer function var a; //lexical enviroment return innerfunction(){ //nested function // action } }
Consider an example:
function externalfunction() { let a = 1; function innerfunction() { a++; console.log(a); }; return inner; } let fn = externalfunction(); // fn = innerfunction, так как функция externalfunction возвращает функцию innerfunction //call inner inner function fn(); // 2 fn(); // 3 fn(); // 4
Another example:
function multiply(n) {//we create a function into which the parameter n is passed var x = n;/write the parameter n into the variable x return function (m) {//the function multiply returns a new function that accepts the parameter m //the internal function will remember the value of x return x * m;//and returns }; } var fn1 = multiply(5); var result1 = fn1(6); // 30 console.log(result1); // 30 var fn2 = multiply(4); var result2 = fn2(6); // 24 console.log(result2); // 24
We can also use another option to call the closure:
var result = multiply(5)(6); // 30
Example from medium.com
function getCounter() { let counter = 0; return function() { return counter++; } } let count = getCounter(); console.log(count()); // 0 console.log(count()); // 1 console.log(count());
We store the anonymous internal function returned by getCounter in the count variable. Since the count function is now a closure, it can access the counter variable in the getCounter function even after it has completed.
This happens because each time count() is called, a new scope is created, but there is only one scope created for getCounter, since the counter variable is declared in the scope of getCounter(), it will be incremented each time count is called, instead to reset to 0.