Check out a free preview of the full Functional-Light JavaScript, v2 course:
The "Closure and Side Effects" Lesson is part of the full, Functional-Light JavaScript, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle reviews closure, which is when a function "remembers" the variables around it even when that function is executed elsewhere. While using closure is a very powerful technique, Kyle demonstrates that side-effects can be produced and how closure can be written in a more pure way.

Get Unlimited Access Now

Transcript from the "Closure and Side Effects" Lesson

[00:00:00]
>> Kyle Simpson: Our next topic of discussion is closure. How many of you ever either had or given or both the job interview question what is closure? Anybody? Okay, I see a few hands maybe some people online will resonate with that. I For a long time before becoming a teacher, I've been a developer now for about 20 years, so I've only been teaching the last five or so.

[00:00:26] So for 15 years, I was just a software developer sitting exactly in your shoes, I worked at consultancies and all that. But I for quite a while was the JavaScript expert if there is such a thing on whatever team I was on. So the jobs that I bounced around to, I just naturally gravitated to I'll be the JavaScript expert.

[00:00:47] And what that equated to was well hey, we need you to come in and vet this candidate figure out if they really know what they are talking about with JavaScript. They sure say something on their resume but do they really know it and I was pretty good at that vetting people.

[00:01:03] With the job interview questions and I countless times asked this question, what is closure? Tell me about closure, tell me an example of using closure in your code some variation thereof. [COUGH] Most of the answers that I would get would range somewhere around, it has to do with asynchronous callbacks, click handlers, timers, things like that.

[00:01:27] And I would say okay, let me prompt you to give me something more, right? What exactly does that mean? Yes, we know that asynchronous callbacks happen in code, but what does it mean to have closure? And when pressed most people didn't have much more to articulate on the topic.

[00:01:42] They've heard of closure but never really processed in their mind what it was. Closure I think can be said to be if not one of them, if not the most certainly in the top 2 or 3 most important Concepts, most prevalent concepts ever invented in all of computer science.

[00:02:04] One of the original ones, actually, it's been around since very, very early days of programming. There is a talk that Doug Crockford gave at one point, he was talking about this topic. He was gonna introduce closure and he was talking in the general sense about anytime a really truly great idea gets invented.

[00:02:30] He would assert that historically, it always takes a full generation of programmers before that truly great idea catches on. And he gave several examples of that, but his somewhat tongue and cheek explanation for why it takes so long for a great idea to catch on is that all of the existing crew are resistant to change.

[00:02:53] They like things the way they are. They don't see any reason why we need to change. And so we basically just have to wait around long and if for them to retire or die off Before the new crowd can come in and say hey this great thing is what we ought to do.

[00:03:08] There's a little bit of truth to that, but obviously it's a little bit overboard. But then he goes on to say, and this is to the point of closure, he goes on to say we know that closure is truly great cuz it took two full generations to catch on.

[00:03:23] If you think back historically to where this came from in JavaScript, closure was kind of one of the original ideas that landed in JavaScript. And it was, the idea behind it was actually there from pretty much from day one. We couldn't observe that until a few editions later, so it was a couple of years before you could really observe and truly.

[00:03:45] Use closure to any power, but at the time, there really weren't that many, if any mainstream consumer oriented languages that had closure in them. We had Pearl, you could argue around the same time, 95, 96, 7. Pearl was coming into its own, and Pearl definitely introduced closure, you could argue that it was a rival in that respect.

[00:04:06] But I would say JavaScript certainly now looking back has captured more of that mainstream consumer developer space than even something like plural. And certainly if you compare it to the main consumer languages of the day, like the C++s and the Javas of the world. Those language didn't have closure.

[00:04:28] They didn't need it, they were very class oriented, procedural, structural, we didn't need closure. You didn't really do functional programming in a sense there, so why would we need something like closure? And JavaScript had this amazing insight. I wasn't there when Bryan and Ike decided this, but I know that he said that his influence for JavaScript was most directly the Scheme programming language.

[00:04:52] And he wanted to put Scheme in the browser, and Netscape was like, yeah that sounds great, come work for us. And as soon as he showed up, they were like no, we're not putting Scheme in the browser. And so he's like, well, How do I do my favorite language that I like in Scheme?

[00:05:07] How do I get those concepts into the browser? So we developed this language that looks like Java, because that's what they told him, they said make it look like Java. But under the covers it really is more related to Scheme, a functional programming language, so he laid the foundation for closure.

[00:05:25] In those earliest days of java script and I think that was a unique almost accidental genius. A stroke of genius to marry this procedural or even class object oriented syntax with these functional concepts. Really I think one of the first mainstream if not the first mainstream language to do so and truly embody the idea of a multiparadigm language.

[00:05:51] And when I came along a few years later in about 1998 or so, when I came along a few years later. What was most interesting to me about JavaScript was not the fact that it was in the browser, but the fact that it was a multiparadigm language. That was fascinating to me and not specifically that you could do any pattern that you wanted.

[00:06:09] You could do procedural, object oriented, or functional. It's not that you could do that, but you could actually mix and match those different paradigms within the same program. And I found that to be fascinating, because ultimately, I like to consider, I get accused a lot of being sort of an ivory tower.

[00:06:26] I'm disconnected from reality cuz all I do is teach but I write a lot of code and I spend a lot of time in your shoes and I like to consider myself ultimately a pragmatist. And what I liked about multi-paradigm is that I didn't have to choose, I could pick which one was correct for any given situation.

[00:06:43] And I think that was and definitely still is one of JavaScript's strong points, is that it doubled down or it made a big bet on this idea of closure. When we fast forward 22 years and if you survey the landscape of major programming languages pretty much every major programing language in existence.

[00:07:06] Certainly, all the consumer orientated ones, they all have closure. Java added closure, PHP added closure. We have Ruby and Python that came along, they all have closure. Every main stream language out there has closure. Even ones that we wouldn't have thought of, like C++ for example. It has closure in it because it turns out it's actually a pretty great idea.

[00:07:27] Turns out it's so powerful that we can implement so many other things on top of it. It is highly prevalent and certainly for the functional program, closure is at the heart of everything that we do. Pretty much everything that we do. We've already been using a bunch of closure up to this point in the code snippets that we've been doing and you might not just have realized what it was.

[00:07:51] So the next time you either give or get asked that interview question, what is closure? Call me crazy, but I'd love for you to have a very specific, articulate answer to that question. Cuz it's a real thing that can actually be recognized and studied and used and understanding what you're talking about instead of, you know it's about call backs.

[00:08:16] Not only I think it will help you get the job but I think it will help you write better code if you understand what you're talking about. So, I wanna give you a definition for closure that you can feel free to use the next time you got asked that question.

[00:08:29] Or feel free to ask this of others and use this as the standard to measure by, it is not the academic definition for closure. If you go on Wikipedia and you try to study what is closure, you're gonna get a whole variety of different descriptions for things and they may or may not line up in various parts.

[00:08:47] Your mileage may vary, as they say, but this is the most distilled down pragmatic definition that I've been able to come up with for what closure is in my experience. And it's based purely on what we can observe about closure. Philosophically, it's just like the if the tree falls in the forest and no one's around to hear it, thing.

[00:09:12] We all know what this is, right? Does it make a sound? Well, if a closure exists academically, but there's no way to observe that closure, does it actually matter whether it exists? I would say not really, so I choose to define closure based upon how we can observe it being different and observation is a really key point here.

[00:09:37] Because you're going to see that closure has been in all the code that you have been writing. If you have been writing JavaScript for any length of time at all you have certainly used closure even if you didn't realise it. So it's not like we're creating a new pattern that you have to come up with and invent and figure out how to use.

[00:09:56] But rather, help you identify, help you be sensitive to observe that as you use it in your programs and to use it on purpose. To use it intentionally and to avoid accidentally having it do stuff that you don't want. There's also a pretty good chance that some of you have had bugs in your program directly related to closure and you may not have realized that that was the problem.

[00:10:19]
>> Kyle Simpson: So let's have a good, clear definition for closure, here it is. Closure is when a function remembers the variables around it even when that function is executed elsewhere.
>> Kyle Simpson: What do I mean by remember? I mean that a function that acts as a variable outside of itself.

[00:10:40] If you then take that function and you run it over here in some other entirely different lexical scope, it still has access to that variable from this scope. It can still update it, read from it, it still is a live linkage back to that variable, even though it's executing in a different scope.

[00:11:02] If you think about it, that maps to what those interview question responses I get are when somebody says, well it has something to do with an event handler. Well yeah, if you've written a click handler before, anybody ever written a click handler? And you put a function in your click handler, you probably referenced some variable, or object, or function from inside of that click handler that was in the scope where you set it up.

[00:11:27] But did you ever stop to wonder, when that click handler runs, it's running in an entirely different location. How does it still have access to the stuff that, actually that stuff we think, you know, conceptually, it should have been garbage collected long before now. But it didn't get garbage collected, it still has access to it and the answer to the question of, how is that possible?

[00:11:50] Closure is what keeps that access alive, it prevents things from being garbage collected. That otherwise would be garbage collected so that function maintains that linkage, that access to it no matter where it goes. When you write a function and you reference a variable outside in some outer scope.

[00:12:09] The entirety of the lifetime of that function it will maintain that closure. You didn't have to do anything extra to make it happen just reference the variable and the closure will be created for you. In a sense closure is a natural extension or almost a requirement for a language that has lexical scope which JavaScript does.

[00:12:30] And a language that has functions as values which JavaScript does. If a function is a value that can be passed around and a function references its variables lexically, that is up the scope chain. That language virtually has to have closure for it to make any sense. It's not an accident that in languages like for example PHP, I can talk about that since I have some experience in PHP.

[00:12:57] I remember writing PHP before they had closure and then I remember writing it after they had closure. And the major difference between the two was that all of a sudden in PHP that had closure functions were values that could be passed around. That was not the case before.

[00:13:14] Now they are values that can be passed around, if a function is a value and its lexically scoped you've got to have closure. It would make no sense, it would be nonsensical to have a function referencing a variable. In this location and it runs here fine but if you take and run it over here all of the sudden it's forgotten about that variable, that'd be nonsensical.

[00:13:38] So that's why I say closure is built into the very core of how our scope mechanisms and our functions as values work. Anytime you've done a click in or anytime you've done a set time out, anytime you've done an Ajax call and received a response back. All of those are scenarios where you virtually certainly were using closure to access stuff after the fact

[00:14:02]
>> Kyle Simpson: Instead of me telling you some brand new thing, it's a little bit more like Neo in the first Matrix movie. In the first Matrix movie, when Neo is gonna see the matrix or when he's revealed the matrix. When they show him the matrix for the first time, they're not showing him something that's brand new.

[00:14:21] They're showing him something that's been there the whole time, and he just couldn't observe it, that's what's happening here. You're seeing something that has been true of your program all along, and now you have a way to observe it when you think about a function that accesses a variable outside of itself.

[00:14:39] Here's one of those examples from earlier in our discussion. The unary utility, the thing that takes a function and makes a new function that's restricted, where's the closure here? Well, the closure's right there with the fn. We pass in an fn, we return back an inner function, this one's called one.

[00:15:00] And I want you to think about when that function from line 2 gets returned and we store that off in some variable like the variable g, for example. That g, if we run it at some point, when we run it, is it in fact not in a totally different scope than scope of the unary utility in line 1?

[00:15:21] When it runs, it's in a totally different scope nd yet, it still has access to that variable. How does it have access? Closure, you didn't have to do anything special. You just made an inner function, used a variable outside of itself. The closure came along for free.
>> Kyle Simpson: I want to put a little bug in the back of your mind here because we're gonna get more into this in a little bit.

[00:15:53] Do you think the unary utility is pure?
>> Kyle Simpson: Given the same function as an input, will it always produce the same wrapped function output?
>> Kyle Simpson: I have a high degree of confidence that the unary utility given the same input would produce the same kind of output. What about the output function itself?

[00:16:29] The function one, is that a pure function?
>> Kyle Simpson: It seems pretty straightforward, right? We're passing in an arg and passing that arg along to fn. The only way that fn could get redefined if it was redefined somewhere between line one and a half and line two and a half.

[00:16:53] Does everybody see that? Those are the only lines in the entire program that could possibly reassign fn. Fn is not actually a constant, we don't have the const keyword there but just by virtue of the way this code is written. It doesn't get reassigned does it? It's not even possible to reassign, so I ask again what's your level of confidence that the one function is gonna behave as a pure function?

[00:17:31]
>> Speaker 2: High.
>> Kyle Simpson: High degree of confidence.
>> Speaker 2: [LAUGH]
>> Kyle Simpson: Goodness, quiet folks today. I set you up for success, I told you the answer. High degree of confidence, that this function one will produce the same outputs, because nobody can redefine fn. Nobody does and nobody can that's a pretty high degree of confidence.

[00:17:54] So that was why it was important earlier for us to expand our definition of function purity to include the ability to reference something outside of ourselves. Because if functions to be pure couldn't reference anything outside of themselves, we couldn't use closure, could we? Do you see where I'm coming from here?

[00:18:15] Closure requires us using variable outside of ourselves. And closure is super important to functional programming Ergo we have to have a definition for function purity that accounts for using variables that are lexically outside.
>> Kyle Simpson: Otherwise closure would be inconsistent with functional programming principles, and there's a whole bunch of functional programming that would come crashing down.

[00:18:44] Most of it. Now, if on line one and a half there was something that did, you know, reassign fn or something like that, well then all of a sudden things get a little bit more interesting, right. All of a sudden we start to say I don't have as much confidence in the behavior anymore.

[00:19:04] So it's all about the context here, but this is a usage of closure which is entirely consistent with the principles of function purity. Here's another example. You remember compose write? Doing the same thing, now we're closing over two different variables, same principle applies. We're able to reference that fn1 and fn2 and this is safe, comp is reliably a pure function or will reliably behave as a pure function because nobody reassigns fn1 or fn2.

[00:19:38] If they did that could be a problem.