This course has been updated! We now recommend you take the JavaScript: From First Steps to Professional course.

Check out a free preview of the full JavaScript: From Fundamentals to Functional JS, v2 course:
The "Closure Recipe" Lesson is part of the full, JavaScript: From Fundamentals to Functional JS, v2 course featured in this preview video. Here's what you'd learn in this lesson:

Bianca reviews the construction and execution of closure.

Get Unlimited Access Now

Transcript from the "Closure Recipe" Lesson

[00:00:00]
>> So, I've been lying to you, we've been talking about closures this whole time. So that concept that we've been talking about is the elusive closure that you've heard of, have you guys heard of a closure before? What is a closure?. Yeah, that's what a function is inside of a function that creates.

[00:00:25]
>> Scope isolation?
>> It's a good way to think of it. Yeah, so a closure happens when you put two functions inside of a function, and you can take advantage of that by returning a function that retains access to its parent function even after it has been executed.

[00:00:48] So that's a closure, and you've been using them. Pretty seamlessly so far, good job. So here's a recipe for closure. So, closures come in different forms, but this is kind of just a guide. So you have a parent function, right? And then you have your inner function, in between your parent function in your child function, you need to make sure that there's some variable there, that you can store value.

[00:01:26] Could be a variable that you declare or it could be a parameter value as well. Then, inside the inner function, you either want to access or manipulate the function in the parent scope. And then you return that function, so that later you can call it and do whatever fun stuff that you wanna do.

[00:01:53] Cool, so that's how you create it and then there's the execution part. And so the execution part is you want to call the parent function, save it to a variable because remember, it's returning a function that we're gonna call later, right? So we need to save it into our variable, this variable is a function, so if I just write out a test, it's gonna return a function.

[00:02:19] And then when you call it it'll execute the function just like we've been doing, it'll return the scope. Any questions? No, okay. So this is a bit of a gotcha, so, when we call this function. So let's see find someone, that's gonna return speak. Right, so let's. Call this someone Speak.

[00:03:03] And we're gonna call it, the first thing that we're gonna do, right? Is we're gonna define that function, nothing is gonna be called yet, who is gonna be defined, and then we return speak. What do you think will happen when we do this?
>> We'll get to function body of speak with [INAUDIBLE].

[00:03:33] Undefined, yeah.
>> Well, we haven't called someone speak yet, okay? So, someone speak is now this function, the question is, do we have access to who?
>> No, because it was defined after the function was declared.
>> Yeah.
>> A block scope inside the original functions that didn't have access across.

[00:04:06]
>> Well.
>> Maybe.
>> It's in, so it's technically in the parent scope.
>> Oops, so doesn't automatically create block unless you use the braces.
>> Yeah.
>> Okay.
>> Exactly, otherwise, you know, I mean, maybe it would be scoped to the it would be scoped to the block, which is this parent block.

[00:04:33] It worked, why did it work? So it worked because as we ran through this function, we defined speak, and then we defined our variable. Now this variable exists in this function execution contexts, and then we returned speak, and then later we called it down here. We went back in here, and this who is gonna look first in its own context and say, do I have a variable called who?

[00:05:13] It's gonna say no, I don't, and then it will look in the parent context and it does. So even though it's visibly after that function definition, it's still valid because it has already been defined. And you can tell by the way that it executes, that's why it's really important to understand exactly how the function executes and in what order Because these kind of tricky things can come up especially when you're like returning functions from functions and all of that.

[00:05:49] So here's a timer, this is one of the more famous examples of using a closure, let's run it All right, so we have our make timer. And we initialize it. So we create elapsed, we create stopwatch was the function, that just returns elapsed, yeah? And then we have, excuse me, we have increase, which increments elapsed, and then we have the set interval and set interval is just a method that will call the function that's passed to it.

[00:06:37] Every 1000 milliseconds, you can change this as milliseconds, 1000 milliseconds is 1 second, so that's why this is a second timer. And then we're going to return stopwatch. So let's check out what timer looks like, and it's just our little stopwatch function. We can see how long ago we call that function here, so we called it about 54 seconds go.

[00:07:07] And so, you can see how you can use a closure to kinda hide away functionality, that you don't want people to mess with, right? So for a timer you're the consumer of this data should only have access to the time, they shouldn't be able to mess with the incremental, increase method or anything like that.

[00:07:33] That you may wanna return the interval, okay she wants to stop it. Cuz it will just go on.
>> You just confuse me, why is it not returning? Since May timer return stopwatch was just the function body of stopwatch and then we act and we, and when we do timer and parentheses, why we're not getting back, why we're not getting back to 0?

[00:08:02]
>> Yeah, it's because. It's because these, all of these shares the same scope. So we only call make timer once, so elapsed, has one value in one execution context, and so we return that great. When we returned it down here we first ran all of this which started an interval, and that interval whether we like it or not, it's just gonna keep running every second and increase elapsed.

[00:08:44] So it's gonna call this function every second, and it's gonna increase that, and so these methods are mutating the value here This function is only reading it. So, it's being changed by these functions, cuz if you think about it, they all live in the same execution context. So if one value is changing it, it's gonna have access to the same value.

[00:09:17] Because we again we make the execution context here, for this one as the parent scope. And just because before we didn't do that, doesn't mean that methods can share scope and change the data, and it can affect other things that are relying on that data. Which goes back to Michael's point, you have to be careful when you're changing your data because it can affect things.

[00:09:52] It's just gonna keep going forever.
>> So what happens if you just run timer without parentheses?
>> It's just a function definition, but it retains access to its parent scope, and that scope is being retained access by this increased function as well. The increased function still has access and is incrementing it, even though we're not doing it, it's being done in the back.

[00:10:28] All right. Here's the same thing with a lot of console logs, to kinda give you a feel, let me make open another tab. So, it will be initialized and it's gonna be elapsed, and then, we are going to say timer, we going to call it, which is going to console log stopwatch