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

Bianca shows a “closure recipe” she created to summarize the components of a closure and how the closure is executed. She also identifies a few gotchas that can arise when using closures.

Get Unlimited Access Now

Transcript from the "Closure Recipe" Lesson

[00:00:00]
>> [MUSIC]

[00:00:03]
>> Bianca Gandolfo: And here's just like a recipe outline, sort of outline, sort of the ideas of how do we create a closure? So the first think is you have to create the parent function. So here we have the function checkscope, and it's a picture so I can't highlight it.

[00:00:22] It goes here. Then we define some variables in the parent's local scope up here, this innerVar. And then you put a function inside of it so the function again could be inside an object as well but it has to be a function. And then you return that function without calling it from the parent function, right?

[00:00:46] So that's how you create the closure, or you start to get there. And then, if you execute, this is how you would execute it. So here's our checkscope, right? We create a variable. We store that return function from checkscope, so we call checkscope here, it goes inside the bracket, we create a local variable.

[00:01:14] Then we see, great, there's an innerFunc, we skip the innerFunc and then we return it here. So we return this innerFunc, so test is now innerFunc which will then just return scope. And then if you just check test and you make sure it's a function. This is optional.

[00:01:33] And then you run test, and test will return if it's a local scope or global scope. And of course we know, since we're all experts at scope now, that it's gonna return localscope.
>> Bianca Gandolfo: Cool? So, that's just a recipe and a way to execute for when you're doing the exercises, you can refer back to these slides to sort of get a step by step.

[00:01:59] Cool, so-
>> Speaker 2: So, there's a slide called gotcha.
>> Bianca Gandolfo: [LAUGH] It's not that bad, it's not that bad. So we have this sayAlice function and we're gonna call it, and let's just,
>> Bianca Gandolfo: And let's just see what it says. So let's start with, who did we leave off?

[00:02:27] Kevin did you go, last time? Okay, so we'll start with Kevin.
>> Speaker 3: So define a function called sayAlice.
>> Bianca Gandolfo: Yep, so we define a function called sayAlice and then Ben?
>> Speaker 3: Skips to the lines-
>> Bianca Gandolfo: You know this class has been the most picked up the skipping the function body faster than any other class I've ever taught.

[00:02:49] Good job, guys.
>> Speaker 3: Go Minnesota.
>> Bianca Gandolfo: Yeah, it's Minnesota, that's what it is.
>> Speaker 3: What about online students, too?
>> Bianca Gandolfo: Yeah, and the world. Maybe I just got better at really emphasizing that. I don't know. So we skip it, and then, Jake?
>> Jake: So we, I guess we start at the bottom at variable what, sayAlice.

[00:03:16]
>> Bianca Gandolfo: Mm-hm. So we call sayAlice and then Tanner?
>> Tanner: We go into our sayAlice function.
>> Bianca Gandolfo: Yeah, we go into the function body and then Phil?
>> Phil: So the first thing you do is you skip the makeLog.
>> Bianca Gandolfo: Well, we recognize that there is a makeLog, we store, and then we skip it.

[00:03:38]
>> Phil: And then assign that text to Alice.
>> Bianca Gandolfo: Mm-hm, and then John? So we're here.
>> John: It's gonna return the inner function makeLog back to the caller.
>> Bianca Gandolfo: Mm-hm, so it's returning this function. So what is now a function. And then if we call, I know which, whatDoesSheSay, that's what we should call it, whatDoesSheSay.

[00:04:22] So what is it going to console.log?
>> John: On the files?
>> Bianca Gandolfo: Good guess. It's actually gonna console log, why hello there, Alice. The reason is is because if you notice when we walk through this code line by line, we initialize this variable alice and it exists. By the time that we call it down here, alice has already been created and assigned a value.

[00:05:01]
>> Speaker 2: So because it's still apparent to makeLog, so makeLog has alice available.
>> Bianca Gandolfo: Mm-hm.
>> Speaker 2: Whether it's done above or below.
>> Bianca Gandolfo: Right, unless you move this up here.
>> Speaker 2: Right.
>> Bianca Gandolfo: Then it wouldn't work,
>> Bianca Gandolfo: Or something, yep.
>> Phil: I have a more fundamental question.
>> Bianca Gandolfo: Sure.

[00:05:25]
>> Phil: On the very first line where you say var sayAlice = function(){.
>> Bianca Gandolfo: Mm-hm.
>> Phil: Could you rewrite that to say function space sayAlice parentheses?
>> Bianca Gandolfo: Yes, you could.
>> Phil: That would be the same thing?
>> Bianca Gandolfo: Basically, yes.
>> Phil: Okay.
>> Bianca Gandolfo: The cool thing about the fact that we can save a function to variable like this shows us that in JavaScript, a function is just data.

[00:05:54] So that's kinda cool and that's why we can return functions from functions like makeLog, is because of that.
>> Phil: So, if on the second line, makeLog, if you wrote that function space makeLog parentheses, you wrote it that way, you can still return it?
>> Bianca Gandolfo: Yeah, you can return it anyway.

[00:06:16] So this is an anonymous function stored in a variable. If we had makeLog,
>> Bianca Gandolfo: Like this, function makeLog, this is called a named function. So this is getting-
>> Phil: Working this case the same way?
>> Bianca Gandolfo: Yeah, it would work the same way. And you could even do-
>> Phil: So why would we call it?

[00:06:41]
>> Bianca Gandolfo: Why would you use one over the other?
>> Phil: Is it a matter of personal preference or?
>> Bianca Gandolfo: It's mostly, it has a lot to do with scope actually is where at what point in your code can you call the function? If you store it in a variable like makeLog, then you can't call the function until this line has been called in that scope.

[00:07:11] But if you had it the other way, we could call makeLog up here. Something called hoisting which happens to all variables, but when you name a function, it doesn't hoist the initialization of it, it hoists the entire definition. So you could call it and the reason it's a little bit dangerous to do it this way is because if you have an if else statement with two functions of the same name, and the hoisting will overwrite it in ways that aren't expected.

[00:07:43] So in general, I recommend just to call it to store in a variable like this.
>> Bianca Gandolfo: Cool.
>> Speaker 2: So I think I was confused about the value of Alice because we're defining Alice after makeLog but because it's still in the parent scope of that console log has access to variable.

[00:08:11]
>> Bianca Gandolfo: Mm-hm, because we actually initialize this and, excuse me, and gave it a value before we actually called makelog.
>> Speaker 2: Is that because of hoisting as well, it hoists it to the top of the function, sayAlice function?
>> Bianca Gandolfo: Yeah, that's part of it, but the fact that it has a value is because of the order in which it's called, yeah.

[00:08:39]
>> Bianca Gandolfo: So here's a stopwatch example.
>> Bianca Gandolfo: So,
>> Bianca Gandolfo: Let's see. So makeStopwatch is called here, so we enter into this block of code. And it's gonna console.log('initialized') and we're gonna set elapsed at 0. Then we're gonna console.log(elapsed), just to see what it is. And you'll notice too that these two console logs will only be run once every time you call makeStopwatch.

[00:09:15] So even if we called,
>> Bianca Gandolfo: Called x down here, these two console.log's won't run, because we're not ever going back up here.
>> Bianca Gandolfo: We're just gonna go immediately inside of this function. So then we have this stopwatch function which all it will do is console.log('stopwatch') and return elapsed.

[00:09:40] But we're gonna skip over it cuz we haven't even called it. Then we have this increase function which is on a setInterval. So like setInterval, I'm sorry, like setTimeout that we saw earlier, setInterval will just, it's not a blocking operation, it will just call increase every one second basically forever.

[00:10:03] So, we'll just keep calling increase, so this is our stopwatch, it will keep the time. And then when we return stopwatch, and again, stopwatch is this function, that's just gonna return elapsed. So let's investigate. So let's investigate what happens.
>> Bianca Gandolfo: Let's pop this out, see if I can make it bigger.

[00:10:33]
>> Bianca Gandolfo: Nope.
>> Bianca Gandolfo: Hm, it's not making it, there we go. So I'm just putting that code in there and then we can say var watch = makeStopwatch and we're gonna call it. And so we see that initialized and 0 are called and we have otherWatch and we can do makeStopwatch again, oops, makeStopwatch again.

[00:11:04] And we see that those two console logs happen, the very beginning here again. However, when we call watch,
>> Bianca Gandolfo: Initialized and 0 aren't running and that shows us that this code up here is only run once. So that scope is created once and then we will call this down here, the body in here will be run again.

[00:11:38]
>> Bianca Gandolfo: So we have watch. And then we have otherWatch, 38,
>> Bianca Gandolfo: Etc.
>> Bianca Gandolfo: That make sense? So that's just another example of how you can use closure.