Definition and characteristics

It is a known fact that when a function ends, all its local variables are picked up by the garbage collector and they cease to exist in memory. However, this is not the case for a function that contains a closure function.
Closures are functions that have access to variables that are in the domain of another function. This is most often achieved by embedding the function inside another function (thus defining the “scope chain”), after which the closure gains the ability to remember the reference to variables from the parent domain.
It should be noted that mutable external functions are not deleted upon execution of the function itself, but are kept in memory to be available to the closure function. After the execution of the closure function, the external function is also closed (hence the name “closure“). Until the closures are executed, JavaScript will also store the necessary variables from the domain of other functions, therefore they take up more memory than regular functions. Excessive use of closure can lead to increased memory consumption. The latest JavaScript engines manage to partially free the trapped memory, but it is still recommended to be careful when using closure.
As part of the debugger built into the browser, you can see the closure expression and which value of the variable is “remembered” (see picture).
An example of a standard closure f is
The function b() is nested inside the function a() and along the “scope chain” looks for a variable from the function a(), therefore it is a classic example of a closure function.
|
|
function a (){ var x = "This is closure"; function b (){ console.log (x); } b(); } a(); Returns: Ovo je closure |
Not every nested function is a closure
If the inner function does not use a variable from the outer functions in which it is located (along the “scope chain”), then it is not a closure. See the following example:
|
|
function a (){ var x = 5; function b (){ console.log ("This is a nested function, but not a closure!"); } b(); } a(); // Returns: This is a nested function, but not a closure! |
Closure remembers variables from outer function even though the outer function has been executed
It is known that after using the return command, the execution of the function and the existence of its variables in the temporary memory are interrupted. However, “Closure” remembers the variables from the outer function even if it returned a value with return.
|
|
function a () { var x = "This is a closure, even after the outer function has completed and returned a result"; function b () { console.log(x); } return b; } var c = a(); // We assign the return function to the variable "c" c(); // Returns: This is a closure, even after the outer function has completed and returned a result |
Closure “remembers” the reference pointed to by the variable
When it is said that the “closure function” has access to a variable, it means that it has access to a certain place in the memory pointed to by that variable, ie. to its reference at the time of calling “closure function“. If at that place in the memory, i.e. reference changes value, closure will always take the latest current value. The following example shows how the internal function “remembers” the reference and uses the current value in memory.
|
|
function povecajBrojac () { var brojac = 0; return function () { return brojac++; }; } var izbroj = povecajBrojac(); izbroj(); // Returns: 0 izbroj(); // Returns: 1 izbroj(); // Returns: 2 |
Redeclaring a variable
If, after defining clousure, we assign some other reference (place in memory that stores some value) to the variable that needs closure, clousure will use the reference that was in circulation at the time of defining clousure. In the following example, the function sayHello() at the moment of definition “remembers” a reference to the global variable “myName” (“Dragoljub”). So even though “myName” changes the reference which now contains the value “Marko”, the closure still uses the value “Dargoljub”.
|
|
var myName = 'Dragoljub'; var pozdrav = function(name){ return function(){ console.log('Hello ' + name + '!'); } } var pozdravSaImenom = pozdrav(myName); myName = 'Marko'; pozdravSaImenom();// Returns: Hello Dragoljub! |
However, this does not mean that the closure remembers the first defined value of a variable, but remembers the defined value of the variable at the time of definitionclosure. So in the following example the function returns “Marko”
|
|
var myName = 'Dragoljub'; var pozdrav = function(name){ return function(){ console.log('Hello ' + name + '!'); } } myName = 'Marko'; var pozdravSaImenom = pozdrav(myName); myName = 'Pera'; pozdravSaImenom();// Returns: Hello Marko! |
NOTE:
When the “new” keyword is used to create an object inside an outer function, IT DOES NOT CREATE A CLOSURE and the new function does not have a reference to the outer function’s local variable as a closure.
Read more