ResourcesJavascriptGuides

closures

Introduction

Closures are a fundamental (yet confusing) concept in JavaScript that allow functions to access variables from an enclosing scope, even after the outer function has finished executing.

This guide explains closures in depth and it will no longer be a confusing topic for you!

Before, make sure you understand what a scope is. We have article about it: Master Scope in Javascript


What is a Closure?

A closure is created when a function is defined inside another function, allowing the inner function to access variables from the outer function.

Basic example:

function outerFunction() {
  let outerVariable = 'I am from outer scope';
  
  function innerFunction() {
    console.log(outerVariable);
  }
  
  return innerFunction;
}
 
const closureFunction = outerFunction();
 
closureFunction(); // Output: I am from outer scope

The innerFunction retains access to outerVariable even after outerFunction has finished executing!

This happens because of the closure, which preserves the scope chain of the outer function.

Pay attention that the outerFunction returns innerFunction.

Practical uses of Closures

Closures are used in various practical scenarios, such as data privacy, currying, and event handlers.

Data privacy

function createCounter() {
  let count = 0;
  
  const innerFunction = () => {
    count++;
    return count;
  };
 
  return innerFunction;
}
 
const counter = createCounter();
console.log(counter()); // Output: 1
console.log(counter()); // Output: 2

The count variable is private and can only be modified through the returned function, ensuring data privacy.

Currying

function multiply(a) {
  return function(b) {
    return a * b;
  };
}
 
const multiplyByTwo = multiply(2);
console.log(multiplyByTwo(5)); // Output: 10

Currying allows you to create a new function by fixing some arguments of the original function.

Closures in async code

function fetchData(url) {
  return function(callback) {
    fetch(url)
      .then(response => response.json())
      .then(data => callback(data))
      .catch(error => console.error(error));
  };
}
 
const fetchUsers = fetchData('https://jsonplaceholder.typicode.com/users');
fetchUsers(data => console.log(data));

Closures in React

Closures are often used in React for managing state and event handlers.

function Counter() {
  const [count, setCount] = useState(0);
 
  function handleClick() {
    setCount(count + 1);
  }
 
  return (
    <button onClick={handleClick}>
      Count: {count}
    </button>
  );
}

Exercises

Exercise 1: Create a function that returns a counter function with an initial value.

Exercise 2: Implement a closure to create a private variable that can only be accessed and modified through specific functions.

Exercise 3: Create a curried function that takes multiple arguments in separate calls.

Resources

MDN Web docs

On this page