Computer >> Computer tutorials >  >> Programming >> Javascript

Practical Uses for Closures in Javascript?


A closure is the combination of a function and the lexical environment within which that function was declared.

function outerFunc() {
   var name = "TutorialsPoint"; // name is a local variable created by outerFunc
   return function innerFunc() {
      // innerFunc() is the inner function, a closure
      console.log(name); // use variable declared in the parent function
   };
}
let f = outerFunc();
f()

outerFunc() creates a local variable called name and a function called innerFunc(). The innerFunc() function is an inner function that is defined inside outerFunc() and is only available within the body of the outerFunc() function.

Note that the innerFunc() function has no local variables of its own. However, since inner functions have access to the variables of outer functions, innerFunc() can access the variable name declared in the parent function, outerFunc().

You can see that name went out of scope when outerFunc completed executing. But if you look closely, innerFunc that was returned and assigned to f still has access to the name variable. Thus inner func formed a closure over the lexical scope of outerFunc.

Practical Uses

Emulating private methods −Languages such as Java provide the ability to declare methods private, meaning that they can only be called by other methods in the same class. JavaScript does not provide a native way of doing this, but it is possible to emulate private methods using closures.

Example

var counter = (() => {
   var privateCounter = 0;
   let changeBy = (val) => privateCounter += val;
   return {
      increment: () => changeBy(1),
      decrement: () => changeBy(-1),
      value: () => privateCounter
   };
})();
console.log(counter.value());
counter.increment();
counter.increment();
console.log(counter.value());
counter.decrement();
console.log(counter.value());

Output

0
2
1

Use with event handlers

for(let i = 0; i < 4; i++) {
   button = buttons[i]
   button.addEventListener("click", alert(i))
}

if you have 4 buttons in a collection buttons and try to add event listeners like this, any click on those buttons will end up giving undefined as the result. This is because when they'll be called, i will no longer be defined. The way to work around this is to introduce a closure over i.

for(let i = 0; i < 4; i++) {
   button = buttons[i]
   button.addEventListener("click", () => alert(i))
}