What is closure in JavaScript
Understanding Closure in JavaScript
In the vast universe of JavaScript, there exists a powerful, yet often misunderstood concept known as closure. It's not a new concept, but it is integral to understanding how JavaScript works under the hood. Let's demystify this concept together.
What is a Closure?
In basic terms, a closure is a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. It's like a backpack that a function carries around wherever it goes. This backpack has all the variables that the function saw when it was created.
Let's Visualize with a Code Example
Let's look at a simple example. Suppose we have two functions: an outer function outerFunction()
, and an inner function innerFunction()
. The innerFunction()
is defined within outerFunction()
and has access to outerFunction()
's variables.
function outerFunction() {
let outerVariable = 'I am from outer function!';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
let myInnerFunction = outerFunction();
myInnerFunction(); // Outputs: 'I am from outer function!'
In the example above, outerFunction()
has a local variable outerVariable
and a innerFunction()
function which logs the outerVariable
. When we call outerFunction()
, it returns the innerFunction()
and assigns it to myInnerFunction
. Now, when we call myInnerFunction()
, even though the outerFunction()
has finished executing and its context is gone, myInnerFunction()
still has access to outerVariable
. This is closure in action.
Why are Closures Useful?
Closures are not just an academically interesting part of the language; they have practical, everyday uses in JavaScript. Here are a couple of examples.
1. Data Privacy
Closures can help emulate private methods, a concept from object-oriented programming where certain methods are available only within a certain class and are not accessible from outside the class. JavaScript doesn't natively support private methods, but closures provide a way to achieve this.
function Counter() {
let count = 0;
this.incrementCount = function() {
count++;
console.log(count);
};
}
let counter = new Counter();
counter.incrementCount(); // Outputs: 1
counter.incrementCount(); // Outputs: 2
In the example above, count
is a private variable that can't be accessed directly from outside the Counter
function. The only way to increment count
is to use the incrementCount
function, which is publicly accessible.
2. Function Factories
Closures can also be used to create function factories. A function factory is a function which returns other functions with specific behaviors.
function greetFactory(greeting) {
return function(name) {
console.log(greeting + ', ' + name);
};
}
let greetInEnglish = greetFactory('Hello');
let greetInSpanish = greetFactory('Hola');
greetInEnglish('Alice'); // Outputs: 'Hello, Alice'
greetInSpanish('Bob'); // Outputs: 'Hola, Bob'
In the example above, greetFactory
function generates greeting functions based on the input greeting. Even after greetFactory
function finishes execution, the returned functions still have access to the greeting
parameter.
Wrapping Up
Closures might seem like a complex and daunting concept, but once you visualize them as a backpack that a function carries around, it becomes less intimidating. Closures are like the Swiss Army knife in JavaScript's toolbox, versatile and practical for many different situations from preserving state to creating private variables. So next time when you're coding in JavaScript, remember, you're not alone, each function brings along its own little backpack of closures. Happy coding!