Search justacoding.blog. [Enter] to search. Click anywhere to close.

February 18th, 2021

JavaScript Closures and Lexical Scoping – Basic Examples

If you have no idea what closures are or what you can do with them, fear not, we’ll demystify them in this article! We’ll also tackle lexical scoping in JavaScript — a closely related concept.

Some familiarity with JavaScript in general is assumed, here. We won’t be going into tremendous depth on this topic, the aim is simply to “summarize” the concepts clearly and with concise examples.

With that said, let’s dive in!

Our first closure

Here’s a basic JavaScript closure for us to look at. We can use this example to examine how closures actually work:

const someVariable = "global var"

const outerFunction = () => {
    const someVariable = "outer var"

    const innerFunction = () => {     
        const someVariable = "own var"
        console.log(someVariable) 
    } 

    innerFunction()
}

outerFunction()

If you run this code, which variable do you think will get logged to the console?

If you said own var, you’d be correct.

But why does this happen? Let’s break the whole thing down.

Global/outer/own scope

As you can see, we have two functions here.

outerFunction and the function nested within it — innerFunction.

Each function has a variable defined in it’s “own” scope. And there is another, third variable defined in the “global” scope.

In this case, the “outer” scope refers to the variable defined inside outerFunction (it’s outside of innerFunction, but still actually accessible).

In simple terms, the code above outputs own var as this is the first variable JavaScript encounters. This is because that variable is defined in the function’s own scope, and this is the first scope that is checked via lexical scoping (more on that later).

Let’s alter the closure…

Hopefully that made sense. Now, what would happen if we commented out (or removed) innerFunction‘s “own” variable? Like so:

const someVariable = "global var"

const outerFunction = () => {
    const someVariable = "outer var"

    const innerFunction = () => {     
        // const someVariable = "own var"
        console.log(someVariable) 
    } 

    innerFunction()
}

outerFunction()

If you said our output would now be outer var, you’d be correct!

innerFunction‘s own scope is checked firstly, and JavaScript sees that there is no variable named someVariable here. So it’s checking the function’s “outer” scope next, ie. outerFunction‘s own variable.

JavaScript finds the variable now — so this is the variable that gets logged out in the console.

Let’s alter the closure one more time…

Finally, let’s comment out outerFunction‘s own variable, like so:

const someVariable = "global var"

const outerFunction = () => {
    // const someVariable = "outer var"

    const innerFunction = () => {     
        // const someVariable = "own var"
        console.log(someVariable) 
    } 

    innerFunction()
}

outerFunction()

You’ll now notice that global var is output in the console.

Reason being, innerFunction‘s own scope is checked initially, and JavaScript doesn’t find the variable. Then it checks the function’s “outer” scope, and it doesn’t find the variable here either.

Lastly, it looks in the global scope, and finally finds the variable it is looking for!

So what’s lexical scoping?

That’s lexical scoping! Or at least, a simple example of it.

We can see from our example that the “outer” variables are accessible by the “inner” function. Not only that, we can see that JavaScript starts at the innermost scope initially, then searches outwards when looking for the relevant variable within the scope chain.

Every JavaScript function maintains a link to its outer lexical environment.

This lexical environment is what JavaScript is checking in each case. This process/concept is what’s known as lexical scoping.

Another closure example

Hopefully you have a basic grasp on how lexical scoping works with regards to closures, now.

Let’s take a look at another JavaScript closure example. In this example, we can observe how the closure can retain its own private “state” of sorts.

const incrementerFunction = () => {
    let localValue = 0;
    return () => {
        console.log(localValue)
        localValue++
    }
 }

 const incrementer = incrementerFunction()
 incrementer()
 incrementer()
 incrementer()

What do you think the output would be here?

If you said 0, 1 then 2, you’d be correct.

This happens because the closure retains it’s own state, effectively, between invocations. In this case, the “state” I am referring to would simply be the value of the localValue variable. This value is incremented each time our function is invoked, resulting in the output described above.

If we added this to the previous snippet:

...
const incrementer2 = incrementerFunction()
incrementer2()
incrementer2()
incrementer2()

We’d see the same output again, 0, 1 and then 2.

This second function has its own scope, this is entirely separate to the function we created initially (incrementer).

So as you can see, the function’s state is private and relative to that function only, other instances of the function have their own dedicated state!

How can I learn more about closures and lexical scoping?

Hopefully this article has served it’s purpose of giving you a clear (albeit brief) introduction to closures and lexical scoping in JavaScript.

If you’re looking for more in-depth information, there are a lot of good articles out there. I think this one — Master the JavaScript Interview: What is a Closure? — is particularly good.

Head on over to JSFiddle

Of course, along with some reading, the best thing to do is to simply practice.

Head on over to JSFiddle (other similar sites available) and start writing your own closures! You can build on the examples I have provided and use those to develop your own understanding.

There are some subtleties to JavaScript closures that haven’t been captured or highlighted in this article, experimenting with your own code will allow you to really develop a deeper understanding of the concept.

Be sure to check back later…

I’ll be covering other JavaScript/general coding topics in this kind of manner in due course (concise with bare-bones examples) — so be sure to check back later for new articles.

I also like to cover articles that deal with coding challenges/problems/exercises, my most recent one being 4 challenging coding problems for to developers to solve.

So feel free to check those out, too!

Thanks for reading!

Have any questions? Ping me over at @justacodingblog
← Back to blog