Closure
Table of contents
Definition
I think defining closure is really hard. And the definition is different depending on person. So, let me define it on my own.
My definition of closure is 'a technique that limits access to a variable using scopes'.
Example
Please look at the example below. I made a counter.
[example 1]
let num = 0;
function counter() {
console.log(num);
num++;
}
counter(); // 0
counter(); // 1
counter(); // 2
As you might expect it, it really works well. But the problem is, someone can change 'num' variable as it is globally declared.
So to prevent that, we can put the variable inside a function like the example below.
[example 2]
function counter() {
let num = 0;
console.log(num);
num++;
}
counter(); // 0
counter(); // 0
counter(); // 0
As you might expect it, 'num' gets initialized every time the function is called.
To solve the problems in [example 1] and [example 2], closure can be used.
[example 3]
const counter = (function () {
let num = 0;
return function () {
console.log(num);
num++;
};
})();
counter(); // 0
counter(); // 1
counter(); // 2
By writing like that, we can solve the problems mentioned above. In [example 1], the variable was declared globally. Now, it is declared in a function. In [example 2], the variable got initialized every time the function was called. Now, it does not.
Module System
I think the usage of closure has decreased because of introducing module system. That is because in module system, a variable inside a module can't be accessed by someone outside. I think before introducing the system, many programmers used closure with IIFE (Immediately Invoked Function Expression). In [example 3], I used IIFE. Outside the IIFE, no one can access to 'num' variable except using 'counter' function.
Private Fields in Classes
Closure can be used to make private fields in classes. Below is the example.
※ If a constructor returns an object, the constructor does not construct the instance and returns the object.
function Person(name) {
let _name = name;
return {
getName() {
return _name;
},
setName(newName) {
_name = newName;
},
};
}
const person1 = new Person('Bada');
console.log(person1);
// { getName: [Function: getName], setName: [Function: setName] }
console.log(person1._name);
// undefined
console.log(person1.getName());
// Bada
person1.setName('Bada1');
console.log(person1.getName());
// Bada1
But now, private fields are introduced. So, I think this usage will decrease.