JavaScript Closures

Lumen
Lumen
Mar 26, 2019 · 4 min read
Image for post
Image for post
A closure is like a backpack

Across my time studying JavaScript object-oriented programming, I’ve searched for and have been eluded a good, concise definition for closures. For every video or article I found on the subject that defined it, I could find another that seemingly differed from it in at least a slight way. Even the MDN definition — “A closure is the combination of a function and the lexical environment within which that function was declared” — is not exactly illuminating for beginners.

The Web Has Imprecise Definitions for a Closure

function personCalls(caller) {
return function(otherName) {
console.log(caller + ' calls ' + otherName + '.')
}
}
var johnCallsSomeone = personCalls('John') // returns function
johnCallsSomeone('George') // logs 'John calls George.'

The next most common is that a closure is any function that utilizes variables for preserving data.

function add(num1, num2) {
return num1 + num2
}

Both of the prior code examples are examples of closures, but they aren’t closures themselves. Anytime we create a function though, a closure is created at the definition time. Which begs the tantalizing question…

What exactly is a closure (in my thinking)?

A closure is the scope created in combination with lexical scoping that allows a function to access all visible variables at the time of its creation.

It remembers (closes over) its surrounding context (variables and scopes it can reach). Remember, it doesn’t remember values, but it remembers variables.

Common within all the definitions for closures, we notice that functions and lexical scoping rules are key to the concept.

What are the most important lexical scoping rules to recall?

  1. Variables defined in the outer scope can be accessed within an inner scope.
  2. Each time you execute a function it creates a new scope
var str = 'hi'     // accessible globally
function foo(){
var s2 = ' world' // only accessible within foo
return str + s2 // foo can access str since it's in an outer scope
}
str = 'hello'foo() // what will it return?

If you said, ‘hello world’, you are correct. This proves that closures remember variables and not the specific values assigned to them when the closure was created. This feature can be incredibly powerful once you grok it.

What does this mean?

In object-oriented programming, we can use functions, closures and objects to create objects with a private data only reachable via a public interface.

function myDay() {
var list = []
var date = new Date().toString()
return {
date: function(){return date},
add: function(task) {
list.push(task)
console.log('task added.')
},
logAll: function() {
list.forEach(function(task, idx) {
console.log((idx + 1) + ': ' + task)
})
}
}
}
var mar23 = myDay()
mar23.add('woke up')
mar23.add('brushed and showered')
mar23.add('ate cereal and milk')
mar23.date // returns 2019-03-23T09:39:48.976Z
mar23.logAll()
// logs:
// 1: woke up
// 2: brushed and showered
// 3: ate cereal and milk

Here I created an object factory function (myDay) that will allow me to collect everything I did in a day, remember the day the item was created, and log all the things added.

Within myDay I declared private variables for list and date . These can’t be used outside myDay. myDay also returns an object that has a public interface of 3 methods — logAll , add , and date . Since these properties are all assigned functions that were declared within myDay , they remember any variables visible (list & date) at the time of creation. Whenever I invoke .add on an object returned by myDay call. the function assigned to it remembers list via its closure, takes the argument passed to it and then adds it to the list array. Same with .date, within the function it remembers thedate private variable through its own respective closure and returns the object assigned to it. logAll accesses thelist private variable via its own closure too, sees the array and is able to iterate over it and log all items within it.

Take some time to chew it over. In order to understand closures, whenever you create a function, think over what its closure can see at that time and how that could augment your function.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store