Closure is when a function remembers the variables around it even when that function is executed elsewhere. While using closure is a very powerful technique, side effects can be produced. Kyle demonstrates this and explains how closure can be written in a more pure way.
- Let's now turn our attention to closure. We've already sort of mentioned this several times. I wanted to give you a slightly more formal but still very, very informal definition for closure. Okay? This maps somewhat to another definition that I've given this in another one of my workshops but, again, this is all about trying to boil this down to whatever kind of basic takeaways we can get. So, closure's when a function remembers the variables around it even when that function is executed elsewhere.
If a function accesses a variable outside of itself, and then you take that function and you send it somewhere else where it wouldn't normally have access to that variable, the fact that it still has access to that variable is closure. I'm not going to go to extreme depth, length to explain all of that, I wrote a whole book about scope and closure if you're interested in digging more into that topic, but we'll illustrate it in a very basic sense, how closure is going to be something that we're going to use or see being used in our functional programming okay.
So, here's an example. I have a function foo and inside of it I have a variable called count and then inside of that I have another inner function. In this case, it happens to get returned. So, I'm returning a function back, we've already seen the returning function pattern before so we're just seeing that again, but you'll notice that I have that count variable inside of the function and it's referencing a variable outside of itself. Strictly speaking, that's lexical scope but what's important here is that that function gets transported outside of the function foo and even when foo is finished, because foo finishes on line nine and there's microseconds of time that happened between line nine and line 11, 12 and 13 and we would normally think about the whole state of foo going away.
That foo would finish and all of its internal state would just get garbage collected but that doesn't happen in this case and the reason it doesn't is because that inner function has a closure over that variable count. Just by simply referencing it, it gets a closure over it and that means that that scope, that state is going to be kept, it's going to be preserved. So, we return that function back, we give it the name x on line nine and then we call it multiple times and you'll notice that we are actually updating that variable every time.
So, we're getting out a new value each time. That's an exercise of closure. There are many, many other ways to think about closure I'm sure you've seen them with your, you know, assigning click handlers to functions, in referencing variables, setting up timers, ajax callbacks, hundreds of other examples. Here, we see closure because a function is remembering and able to access a variable that was around it, that is, outside of it. Even though we take that function and transport it elsewhere. In this case, returning it out.
Okay? Now, something interesting about this closure that I want to point out, is that while this is closure this is not, strictly speaking, what you'll probably going to see as a very common pattern in functional programming. Because every time I call x, I get a different answer. So, there's an internal state that happening, which means I still have to track that state over time. I have to understand how many times x has been called. It's not an external state that's changing something where that state can be changed in an entirely different way, so, it's not some, you know, free range variable like count hanging out on the outside.
It's hidden within a closure, but there's still side effects happening, in a strictly pure sense. So, the way we're using this function we have two very, very functional concepts being married together, here, but the way we've married them together not as functional. It's a bit impure. That doesn't make it bad. I use this all the time and many of you used this in your programming. But you should be aware, if you're trying to use a functional concept, this usage of closure is perhaps not as functional, not as functionally pure.
Now, how could we use closure in a more effective way as a functional programmer? Same principle will apply, closure is the same principle regardless of how you look at it but how we use it can be different. So, in this case, I declare a function called sumX, it receives an x variable and you'll notice that I'm closing over that x. Just like I was in the previous line. I'm closing over that variable and I'm returning that function. But what's the key difference, here? The key difference is that x never changes.
Does everybody see that? For the lifetime of my reference of that function, which I happen to call on line seven, I call it, add10. For the lifetime of that function, every single time I call it, the x value is always going to be 10. Same principal, still closure but here I'm not allowing it to make some side effecting change where I'm going to get a different answer every time. This is more functional. This is a technique for applying more functional programming idioms to our programs to make them more reasonable.
See, here, I'm making a function an incredibly useful function, and another one you should add to your utility library, get rich and famous. I'm making the add10 function, which takes anything that you add to it like the value 3 and it adds it to the value 10 that's already saved in it's state, saved in it's closure. That turns out, that sort of technique, of creating something, sort of as a specialized thing that it doesn't have other stuff, this goes by fancier terms, so, bear with me for just a moment, it goes by currying or partial application.
Taking a function that would normally need multiple variables and presetting some of those using closure that's called currying or sometimes, depending on how you're using it, whether it's currying or partial application. Kind of two sides of the Rubik's Cube if you ... So, yeah, so, there's some crazy, complex terminology but let's not worry about currying and partial application, let's just worry about this idea that a function can remember the variables that it has around it and we can use that to our advantage to save some state along with the function.
The fact that that state doesn't change over time is what makes this easier to reason at all.
This course was created by Frontend Masters. It was originally released on 03/08/2016. We're pleased to host this training in our library.
- Pure functions
- Manual composition
- Composition utility
- List operations