Javascript Closures

Closures are also known as lexical scoping.  It is a result of functions that can nest, and functions that are values.  The context of the inner function includes the scope of the outer function.  The image below is taken from Crockford’s “The Good Parts of JavaScript and the Web” course on Front-End Masters (I watched on LinkedIn Learning).  The reason that it is called a closure is that the set of variables of the inner function encloses the set of variables from the outer function.

To have closures, the developer of Javascript, Brendan Eich,  needed three things: lexical scoping, nested functions, and functions as values.  According to Crockford, this came from three languages: Lisp, Algol 60, and C.

None of the above languages had closures.  The first language to support closures was Scheme.  JavaScript was the first language to bring this concept of closures to the mainstream.  That is why closures are such a big deal.  But if you have only ever programmed with JavaScript, it can be hard to appreciate how powerful it is.  For the most part, closures just happen as a result of lexical scoping (as opposed to dynamic scoping).  (Lexical scope means the scope is defined based on where variables are declared and written in the code.)  You don’t really have to use any special technique to create a closure.  But understanding what they are can allow you to take advantage of them.  After Javascript, Python, Ruby, C#, C++, PHP implemented closures.  More recently closures were brought into big brother Java.

Below is an example I store an immediately invoked function expression, with a nested function to digit_name.  By storing the names array inside the function expression, I prevent it from polluting the global scope.  This helps avoid collisions and protects data from unintended exposure.  When I call for the definition of digit_name, it gives me the definition of the nested function that was returned.  But I cannot see or have access to the names array.  However, thanks to the closure, I still have access to the lexical scope in which it was defined.  The inner nested function that was returned still encloses the scope of the outer function, and can therefore still access the names array.

var digit_name = (function() {
  var names = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine"
  ];

  return function(n) {
    return names[n];
  };
}());

// function definition stored in digit_name
digit_name
ƒ (n) {
    return names[n];
  }

// variable expression
console.log(digit_name(3))
three

Leave a Reply

Your email address will not be published. Required fields are marked *