Some Closure on Closures
Tags: javascript, closures
Published: 2019-03-06 22:43:57

---
title: Some Closure on Closures
published: true
description: Closures
tags: JavaScript, closures
---

# Introduction

Closures are a concept that take a while for many new JavaScript developers to get used to.  It's one of the more abstract concepts of JavaScript.  A closure exists when you have a function within a function that has access to the outer function's state.

What?

See, that's the definition I always see when someone defines a closure.  But it's not as clear cut as to what it really means, so let me explain

# Execution Context

When a function is called, JavaScript's engine creates what is called an _execution context_.  This context contains all the state required for that function.  In simple terms, state is simply the variables and their current values.

```javascript
function foo() {
    const a = 3;
}
```

In the function `foo()` above, when you call `foo()` an execution context is created, the variable `a` is set to `3` and then the function ends, the context is destroyed and the variable is destroyed and the function returns `undefined`.

> This is also how scope works.  `a` is declared in the function and only exists within that function and any lower blocks that may appear in that function.

Any internal functions within `foo()` can access `foo()`'s state.

```javascript
function foo() {
    const a = 3;
    function log() {
        console.log(a);
    }
    log();
}
```

But this is just basic scoping right?  Well yes, in this example, but here's what's powerful about closures.  If the outer function `foo()` is destroyed, the internal `log()` function, if it was brought out of the function, would still have access to `foo()`'s state.

```javascript
function foo() {
    const a = 3;
    function log() {
        console.log(a);
    }
    return log;
}

const log = foo();
log();    // logs 3

// foo()() would also be acceptable, and would also log 3
```

The internal `log()` function still has `foo()`'s execution context, even though `foo()` was called, created, and destroyed.

To illustrate this further, let's make `foo()` take a parameter rather than a hard coded variable.

```javascript
function foo(a) {
    function log() {
        console.log(a);
    }
    return log;
}

const log3 = foo(3);
const log4 = foo(4);

log3();    //logs a '3'
log4();    //logs a '4'

// alternatively
foo('hello')();    //logs 'hello'
```

Here you can see `foo()` is called 3 times with different values for `a` and the returned function still "remembers" the value of `a` from the execution context.

That's essentially what a closure is.  It's an internal function that has access to the the outer function's state.

# But Why?

Why would I need to use this?  Well, there are a number of situations where its useful to utilize closures.  Generators use closures.  Event handlers use closures.  Partial application of functions use closures.  Closures are a major component of functional programming.

Here's how you can create a generator in JavaScript.  This one is similar to (but simpler than) Python's `range()` object:

> This is a handmade generator by the way, rather than the built in generator syntax that comes with JavaScript.  For more information on the official JavaScript generators, check out the [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator)

```javascript
function range(start, end, step=1) {
    let count = 0;
    return () => {
        count += 1;
        if(start < end) {
            return start += count !== 1 ? step : 0;
        } else {
            return false;
        }
    }
}

const r = range(1, 5);
console.log(r());    // logs 1
console.log(r());    // logs 2
console.log(r());    // logs 3
console.log(r());    // logs 4
console.log(r());    // logs 5
console.log(r());    // logs false
```

> The ternary `count !== 1 ? step : 0;` is used to ensure the range includes the start value

The `range()` function returns an anonymous function that keeps track of the current state of the three parameters passed into the function.  Each time you call `r()`, it will return the next iteration of that state, which is mutated by the expression `start += step`.  Starting with this range object, it's not terribly difficult to use closures to rewrite many of the JavaScript array functions to functional functions that work on generators instead.

Here's what `map()` might look like.

```javascript
function map(mapping) {
    return (range)=> ()=> {
        const value = range();
        if(value && value !== false) {
            return mapping(value);
        } else {
            return false;
        }
    }
}

const squares = map(x => x ** 2)(range(1,5));
console.log(squares());    //logs 1
console.log(squares());    //logs 4
console.log(squares());    //logs 9
console.log(squares());    //logs 16
console.log(squares());    //logs 25
console.log(squares());    //logs false
```
> Note that with arrow notation `()=> ()=> {}` is what a closure would look like.

Here you have a generator to create square numbers.  Each time the function is called, it "remembers" the execution context of the outer function.

You can, of course, loop over the generators as well.

```javascript
let s;
while(s = squares()) {
    console.log(s);
}
```
> Don't get confused with the expression in the while loop.  That `=` is an assignment operator, not an equality operator.  `=` is a function under the hood however, and it will return the value of `squares()`, which is either a number, or false, and thus we can take advantage of truthy/falsy here.

But I felt writing it out was clearer.

You can see the code for these generators in action at [Repl.it](https://repl.it/@jkuhl87/WheatTameWebportal)

# Saving State

Closures also work when you need to save state.  Imagine you have a large app that needs to connect to multiple mongo databases.  I have an express back end and I need to export multiple connection functions to multiple javascript files.  A closure can be a simple way of doing this:

```javascript
//in a file called "database.js"
const mongoose = require('mongoose');

const user = process.env.MONGO_USER;
const password = process.env.MONGO_PW;
const db1URI = `mongodb+srv://${user}:${password}@cluster1.mongodb.net/database1?retryWrites=true`;
const db2URI = `mongodb+srv://${user}:${password}@cluster2.mongodb.net/database2?retryWrites=true`;
const db3URI = `mongodb+srv://${user}:${password}@cluster3.mongodb.net/database3?retryWrites=true`;

// wrap the connection in a closure so I can export it with the URI
function Connect(uri) {
    return function() {
        mongoose.connect(uri, {
            auth: {
                user,
                password
            },
            useNewUrlParser: true
        });

        const db = mongoose.connection;
        db.on('error', console.error.bind(console, 'connection error'));
        db.once('open', ()=> {
            console.log('\nSuccessfully connected to Mongo!\n');
        });
    }
}

const db1Connect = Connect(db1URI);
const db2Connect = Connect(db2URI);
const db3Connect = Connect(db3URI);

module.exports = {
    db1Connect,
    db2Connect,
    db3Connect
};
```

Then in various modules in your Express code you could say

```javascript
const MongooseConnect = require('./database.js');
MongooseConnect.db1Connect();

//and in another file somewhere else
const MongooseConnect = require('./database.js');
MongooseConnect.db2Connect();

//etc
```

Here the `Connect()` method saves the URI parameter passed in in a closure so that later when you actually call it, it can connect to Mongo (through Mongoose) with that URI.  This allows me to have one single function for connecting and one central location with all the connection strings gathered in one spot.  I could simply export a function and pass the string as a parameter, but then I'd have to define a connection string in different files that use the `Connect()` function or have an object defined in another file with all the connection strings in one spot.  With a closure, I can simply export the functions and have all my connection strings in one spot where I can maintain them with ease.

# Events

Closures also work with asynchronous operations and events.  In fact, when you pass a callback to a click handler, that is by definition a closure.  `addEventListener` is a function, the handler you pass into it would be the closure.

Here's a piece of code I wrote when it finally clicked how a closure works for me:

```javascript
function clicker() {
    let counter = 0;
    const myDiv = document.getElementById("mydiv");
    const btn = document.querySelector("button");
    btn.addEventListener('click', ()=> {
        myDiv.innerHTML = counter;
        counter++;
    });
}

clicker();
```

I had a need to have the event listener added to a DOM element within a function and I wrote the above to make sure the concept itself worked.  It's a simple counter, you click on a button the number goes up.  Hurray, I guess.

But the point is, the anonymous click event handler still has access to the `counter` variable and the `myDiv` element, even though the `clicker()` function will already have its execution context destroyed by the time the user clicks the button (unless he's got a super fast millisecond reaction speed I suppose.)  Even though `counter` and `myDiv` are scoped to `clicker()`, the event handler can still access them.

Asynchronous functions and events work just fine with closures because that closure _still_ has access to the state of the enclosing function even if there's some time between the destruction of the enclosing function and the calling of the closure.  If you have some closure that calls some network API and it takes 250 milliseconds to get a response, then that's fine, the closure still has access to the enclosing state.

# Summary

Closures are tricky to understand.  Hopefully some of the examples above made it clearer how they work.  Remember, a closure is simply an internal function that has access to the state of the function that it is contained in.  Here's an idea to get a better handle of closures, use the `range()` function I provided above and try to make a `toArray()` method that gives an array for each value in the generator.  Or try to make a `filter()` function or rework any of the other JavaScript Array methods to work on `range()`.  I've made a few on my own and they'll all require you to use closures.

Thank you and happy coding.