Jump to Categories

Closures

A closure is a function defined within another scope that has access to all the variables within the outer scopeEric Elliot, EricElliottJS.com

In JavaScript, if you use the function keyword inside another function, you are creating a closure. Closures are the primary mechanism in JS to enable data privacy.

An example of a closure

function nameMe() {
  var name = 'Shane';
  function showName() {
     console.log(name);
  } 
  showName();
}

nameMe();

The variables within a closure are still acessible after the function has been returned. For example user1 can access their data - as it existed when the closure was created when personInfo was called - at any time. You are unable to get/access data from outside the scope, but can access what you need within the closure.

const personInfo = (a, b) => {
  const obj = {}
  const name = a;
  const DOB = b;
  return {
    registered: () => {
      return `${name} is registered`;
    },
    sayAge: () => {
      return DOB;
    }
  }
}

const user1 = personInfo('Shane', 1986);
console.log(user1.registered());
console.log(user1.sayAge());

// Undefined
console.log(user1.DOB);

Uses of closures

Self invoking function (IIFE)

In the following example btnCount self-invokes, returning a function expression.

<button onClick="btnCount()">Btn 2</button>
const btnCount = (() => {
  let count = 0;
  return () => {
    ++count;
    console.log(count);
  }
})();

Function Factories

One powerful use of closures is to use the outer function as a factory for creating functions that are somehow related.

const sayname = (title) => {
  return (name) => {
    return `Hi ${title} ${name}`;
  }
};

const doctors = sayname('Dr')
// Hi Dr James Smith
console.log(doctors('James Smith'));

Namespacing

Making public and private methods by using a IIFE to make a closure.

const test = (() => {
  let privateNumber = 100;
  return {
    sayNumber: () => {
      return privateNumber;
    }
  }
})();

// 100
console.log(test.sayNumber());
// Undefined
console.log(test.privateNumber);

Check out this excellent analogy on Stack Overflow.

Refs