
Photo by Pakata Goh on Unsplash
JavaScript Closure 101: An Introduction to the Fundamentals
Learn about the concept of closure in JavaScript, including how it works and how it can be used to create private variables or pass functions around.
Table of contents
No headings in the article.
JavaScript's closure feature enables developers to compose functions with access to variables beyond their scope. This makes it perfect for creating both private data and functions, as well as callable objects that can be used in different contexts. In this blog post, we'll delve into how closure works and how you can use it practically.
If you're looking to learn more about the advantages of closures in JavaScript, click the link to check it out.
First, let's start by looking at how closures are created in JavaScript. A closure is created when a function is defined inside of another function, and the inner function has access to the variables and parameters of the outer function. Here is a simple example:
function outerFunction(param) {
const outerVariable = 'I am a variable in the outer function';
function innerFunction() {
console.log(outerVariable);
console.log(param);
}
return innerFunction;
}
const closure = outerFunction('I am a parameter');
closure();
// I am a variable in the outer function
// I am a parameter
In this example, the innerFunction
has access to the outerVariable
and the param
variable, even though they are defined outside of its own scope. When the closure is created by calling outerFunction
and assigning the returned innerFunction
to the closure variable, the innerFunction
maintains a reference to the outerVariable
and param
. This means that when the closure is called, it is able to access and use these variables, even though they are no longer in the same scope.
One important thing to note is that the closure maintains a reference to the variables, not a copy of the values. This means that if the outerVariable
is changed after the closure is created, the closure will have access to the updated value. For example:
function outerFunction() {
var outerVariable = 'I am a variable in the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction('I am a parameter');
outerVariable = 'I am now a different value';
closure(); // 'I am now a different value'
In this case, when the closure is called, it will log 'I am now a different value'
instead of the original value of outerVariable
.
Now that we have a basic understanding of how closures work, let's look at some practical applications. One common use for closures is to create private variables and functions. Since the inner function has access to the variables and parameters of the outer function, it can use these to create private variables and functions that are not accessible from the outside. Here is an example of a closure used to create a private counter:
function counter() {
let count = 0;
return function() {
count++;
console.log(count);
}
}
const closure = counter();
closure(); // 1
closure(); // 2
closure(); // 3
In this example, the count
variable is defined inside the counter
function and is not accessible from the outside. However, the inner function returned by the counter function has access to count
and is able to modify its value. This allows us to create a simple counter that can be incremented, but the count
variable is not directly accessible from the outside and cannot be modified except through the use of closure.
Another common use for closures is to create functions that can be used in different contexts. For example, consider the following code:
function greet(greeting) {
return function (name) {
console.log(greeting + ", " + name);
};
}
const sayHello = greet("Hello");
sayHello("John"); // 'Hello, John'
sayHello("Jane"); // 'Hello, Jane'
const sayHi = greet("Hi");
sayHi("John"); // 'Hi, John'
sayHi("Jane"); // 'Hi, Jane'
In this example, we have defined a greet
function that takes a greeting
as a parameter and returns a function that takes a name as a parameter and logs the greeting
and name
. We then create two different closures using the greet
function, one for saying hello and one for saying hi. These closures can be used in different contexts, allowing us to easily reuse the same greeting logic with different greetings. Closures can also be useful for creating functions that need to maintain state. For example, consider the following code:
function createAdder(x) {
return function (y) {
return x + y;
};
}
const add5 = createAdder(5);
console.log(add5(3)); // 8
console.log(add5(4)); // 9
const add10 = createAdder(10);
console.log(add10(3)); // 13
console.log(add10(4)); // 14
In this example, we have defined a createAdder
function that takes a number as a parameter and returns a function that takes another number as a parameter and returns the sum of the two numbers. We then create two different closures using the createAdder
function, one for adding 5 and one for adding 10. These closures are able to maintain their own state, allowing us to easily create adder functions for different values.
There are many other ways in which closures can be used in JavaScript, and they are an important concept to understand for anyone working with the language. Whether you are creating private variables, passing functions around, or maintaining state, closures can be a powerful tool in your JavaScript toolkit.
Visit Frontend Mag to read more useful front-end web development articles!