Deep JavaScript Foundations, v3

What is Closure?

Kyle Simpson

Kyle Simpson

You Don't Know JS
Deep JavaScript Foundations, v3

Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "What is Closure?" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle defines what it means to close over variables and indicates where in a function it is occuring.


Transcript from the "What is Closure?" Lesson

>> Kyle Simpson: To define closure from an observational perspective, rather than from a whether it exists or not sort of a perspective, the academic question. Here's that definition, and as far as I'm concerned, this is the right answer to that interview question from here forward, until somebody tells me a different answer, a different definition that is more distilled than this, which I haven't come across.

This is the right answer to that question, what is closure? Closure is when a function is able to remember and access its lexical scope, the variables outside of itself, so-called free variables, when it's able to access that lexical scope, even when that function executes in a different scope.

Let's take that first part. That closure is able to access its lexical scope. We already know that. That is lexical scope in itself, is that a function can reference variables outside of itself and it just goes up the scope chain to find it. The second part is the critical part, and without these two parts, you don't have closure.

You have to have both. Without the second part, it's just lexical scope. With the second part of this definition, which is, even when the function is executed in a different scope, now we start to see something interesting. Cuz when you take a function and you pass it as a callback, or you take a function and return it back, and the scope that it was originally defined in has otherwise, at least conceptually, gone away.

And we would think, normally, it's been garbage collected, it's done. But there's a function that survived that was defined within that scope. It turns out that the scope didn't go away at all. It turns out that this function is able to hold on to a reference to that scope, and wherever you pass the function, it continues to have access to that.

That doesn't happen by accident. That's not magical, that's closure. The preservation, the linkage back to the original scope where it was defined, no matter where you pass that value, no matter where it executes, it retains that value. It preserves that scope. That's called closure. So let's take a look at a couple of examples, ones that you'll probably recognize right off the bat.

Surely, all of you have done a timer at some point or another, a set timeout or a set interval, and I bet when you passed in a function to your timer, it referenced some variable outside of itself. What's also probably true is you never stopped to consider, how does that work?

Because at the time that this function waitASec runs, the ask function has already finished, and the variable question which its closed over should have gone away. But it didn't go away because closure preserved it, so-called the waitASec function is closed over the variable question. That's a closure, okay?

Now, academically, they think about closure on a per variable basis, meaning only the variables that I'm closed over, those are the only ones that are preserved. Technically, it's possible that that could be the case. Certainly, that would only be what you could observe. But I would caution you to consider that generally speaking, at least the latest information that I have, JavaScript engines essentially implement closure as a linkage to the entire scope, not on a per variable basis.

Technically, they should be able to close over individual variables or remove variables that aren't closed over, but essentially, as far as I'm aware, closure is on a per scope basis. So if you have a variable that's holding on to a really big piece of data and then you create a closure, even if you're not referencing it, that data may stick around and not get garbage collected.

So it's best to assume that closure, even though academically it's per variable, it's best to assume closure is a scope-based operation. And it's not something you have to do special with a function, other than you just have to access a variable outside and then you have to pass the function somewhere.

That's all you have to do to observe the idea that closure exists. Think about what it would be like if you had a function that didn't have closure. If you're in a language that had first class functions, lexical scope, but didn't have closure, you'd pass this function somewhere, and all over sudden, it would forget about all its variables.

Wouldn't be that helpful, would it? It's almost as if closure falls out as a necessary requirement, a necessary third component of a lexically scoped language with first class functions. If you have those two, you're gonna have closure because it wouldn't make sense not to. That's what closure is.

And whether you do timers or not, you've certainly all written or at least accessed code that returns functions or passes them around in callbacks, and that's the exact same thing. If I returned a function here that is closed over the question variable, then even though the ask function has finished, by line 11, we still have access to that variable.

Not a snapshot of the variable, but the actual variable itself. That's called closure.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now