Check out a free preview of the full JavaScript: The Hard Parts, v2 course
The "Returning Functions" Lesson is part of the full, JavaScript: The Hard Parts, v2 course featured in this preview video. Here's what you'd learn in this lesson:
Will diagrams what is happening when a function returns another function, and drives home the point that by assigning a variable to the result of a function that returns a function, that it's possible to then call the internal function by using the named variable.
Transcript from the "Returning Functions" Lesson
[00:00:00]
>> Will Sentance: But it all starts with us returning a function from the invocation, from the running of another function. This is a big part, it's a part that's gonna feel, okay, yeah, I kinda get this. And yet, folk, if we get this bit down, everything enclosure follows like that, like it's easy.
[00:00:22]
But we have to understand what sounds pretty from returning a function another function. And yeah, I promise you I've given this talk. I'm not assessing more, I give this talk at insert companies who knows what this is my be and this season engineers. They really don't have this little notion down.
[00:00:38]
And until we do A, anything really understand JavaScript. And B, we definitely don't have the ability to get closure, right? Of course, cuz we don't have closure ready. So we're gonna go and understand returning a function of another function, here it is. Functions can be returned from other functions in JavaScript, let's walk through it.
[00:00:55]
We've got a function saved here from createFunction, we're gonna give a label generatedFunc, an identifier. GeneratedFunc, to which we're gonna assign the output of running create function. One time running create function. How do we know that? I see parens, it says go run this code up here. We're gonna create an execution context to run it, dive in, we're gonna save immediately a brand new function.
[00:01:17]
Call multiplied by two. We're not gonna use it, we're instead gonna return it straight out into generatedFunc. Such that generatedFunc is gonna be a new label for the function that was born as multiplyBy2. In global, the local label multiplied by two inside of create function's execution context, that's gonna be deleted.
[00:01:35]
But their functions are gonna be returned out in the generatedFunc and we'll now gonna have a new label for what was born as multiplyBy2 generatedFunc. It's kinda like the flip of the other one where we were taking something into another function, give it a new label. Now, we're taking it out, giving it a new label and running it by that new label with params.
[00:01:51]
That generatedFunc is really gonna be multiplyBy2. Sounds maybe not profound, but folk, we get this down, closure follows so naturally. All right, here we go. Line 1, Todd, what are we doing here?
>> Todd: We're defining the function createFunction.
>> Will Sentance: CreateFunction, and we're storing it where?
>> Todd: In global memory.
[00:02:16]
>> Will Sentance: That's right we're actually storing all the code of the function never lose sight of this box represents all the code of the function being defined, being saved into global memory. Perfect, thank you to Todd. And now we move on to what line next? Ethan?
>> Ethan: We'll be defining the concepts generatedFunc.
[00:02:41]
>> Will Sentance: Beautiful, define the const generatedFunc. There it is generatedFunc, okay? Now, things got interesting Ethan, we sold that label, that identify that const label generatedFunc. What are we're gonna store assign to it? What's it's value gonna be?
>> Will Sentance: The answer might just be, we don't know yet.
>> Ethan: We don't know yet.
[00:03:05]
>> Will Sentance: We don't know yet, it's uninitialized, while we've gotta go and, you can't get away with that, we've gotta go and do what, Ethan?
>> Ethan: Call createFunction.
>> Will Sentance: Call createFunction and whatever it returns out, uninitialized for now, we are going to go off and pull createFunction, no arguments, no inputs, no problem.
[00:03:33]
All he was a normal make a function run. Parentheses will make a function run. It's a big distinction. And we're going to enter that execution context. We're gonna create everybody because after lunch shows what? We're gonna create a brand new?
>> Todd: Execution context.
>> Will Sentance: As we go and here, okay, whatever is returned out of this function, it could be a number, it could be a string, it could be an array, it could be a definition the code of a function is gonna be stored into generatedFunc.
[00:04:09]
But before we get to that, Braden, what is it that we're going to declare, save, store inside createFunction's execution context? What are we storing there?
>> Ethan: You're declaring the multiplyBy2 function.
>> Will Sentance: Yeah, and that literally means, people, this is local temporary memory we define. That's not spelled, right?
[00:04:31]
Define multiplyBy2 as, I'm gonna do a different colors so we can really track its journey to find multiplyBy2. Is that readable? That's okay, define multiplyBy2 as a function is whole code. Now, Kayla are we using multiply by two right now? Are we gonna call it, invoke it inside of createFunctions execution context?
[00:04:56]
>> Kayla: No.
>> Will Sentance: We absolutely not, what are we gonna do instead here, Kayla?
>> Kayla: We're gonna return it to the constant generatedFunc.
>> Will Sentance: Fantastic, we're gonna return it out into the constant generatedFunc. Here's what JavaScript does, it seems returned, multiplyBy2, it goes, I've no I don't return means, the next thing is gonna be the output of this function execution context.
[00:05:17]
In fact, this is gonna replace the call to the function and we saw it on the left hand side here. I know that but I have no idea what this word means. So it goes off as it always does to look into memory. Don't worry. There's a function, it uses that label to take the value, which believe it or not function definition is a value.
[00:05:37]
The code of a function is a thing that can be stored that has a lot of value with the thing that can be stored with a label. Label for identify, a fancy name for it value, which is the whole code of the function. We're talking, if we were to take it, it would be everything but the label.
[00:05:52]
Everything there but the label, that's the body of it. ReturnNumBy2, that's the parameter of it, num. All stored, that's what this is here. I'm gonna grab, and exactly as Kayla said, we're gonna return it out. Kayla, does it come, does it get returned out with its label multiplyBy2?
[00:06:08]
No, just the definition into what new global label, Kayla?
>> Kayla: GeneratedFunc.
>> Will Sentance: Into generatedFunc, she's spot on. There it is, it was formally known as, just for our purposes of keeping track of it, it was formerly known as multiplyBy2, but not anymore, okay? That is also to say by the way, I might even show it here.
[00:06:30]
That is to say that we are literally replacing that function call and it's gonna return out that function definition of multiplyBy2 into generatedFunc. Okay, [SOUND], that's tricky. And this execution context, everybody, what happens to it?
>> Todd: Disappears.
>> Will Sentance: Yeah, it disappears, it's deleted, it's closed, everything inside of gets deleted.
[00:06:52]
Well, except the function got returned that but we do lose that label everything besides a bunch of efficient outcomes. Okay, now we're back into global, where we hit left hand side of the next line. It says to do what Ryan on the left hand side of the last line there.
[00:07:08]
>> Ryan: Define a constant result.
>> Will Sentance: Define a constant result, very nice. Okay, define a constant results.
>> Will Sentance: And so that equal to what? Ryan go ahead.
>> Ryan: GeneratedFunc.
>> Will Sentance: Not quite, I wouldn't even say that words where the precision is so important here. Kayla do you wanna take a shot?
[00:07:31]
>> Kayla: It's the result of calling generatedfunc with 3.
>> Will Sentance: Yeah, so let's write it here, she's exactly right. You see it's really important here that we distinguish between a function. If we just had no parens here, the result would be generatedFunc. And it would just be another label for this function here.
[00:07:49]
But instead, this is a command to go and run this function here. So now let's be really precise on this. Kayla, generatedFunc, if you're looking at this code here, and this what people do all the time, and totally understandably. You look up and you say what's generatedFunc? It's the, well, what is generatedFunc?
[00:08:07]
Kayla, do you wanna give it a shot?
>> Kayla: It was the definition of multiplyBy2.
>> Will Sentance: She's spot on, more generally to give you sort of another way of putting it, in terms of createFunction. What's its relationship to createFunction?
>> Kayla: It was the result of running it.
>> Will Sentance: It was the result.
[00:08:24]
It was the result. The one time running of createFunction. GeneratedFunc people, has zero relationship from that line on, from this penultimate line on generatedFunc has zero relationship with createFunction, it has zero connection. And yet what do we look at that when we see that? We're like generatedFunc is kind of the running of createFunction or even generatedFunc is kind of createFunction.
[00:08:56]
No, so JavaScript is a synchronous language. Do the line, move on, never to touch it again. When you've done that line, the running of createFunction, you go in, you create a new function, multiplyBy2 inside. It gets returned out into generatedFunc. GeneratedFunc is pure and simply and only the result of the one time running of the create function.
[00:09:21]
That is to say that it is saved, multiplyBy2's code on a generatedFunc. It has nothing to do from that line on with createFunction. And yet, are we prone we see this line here? When we see generatedFunc refer to, we go up and we see it's related to createFunction.
[00:09:36]
We assume, somehow it's got some relation to createFunction. It has zero relationship.
>> Will Sentance: It's quite extraordinary how little connection it has. It's was a one-time, I know I'm dwelling on this, but I promise you people, people around the world are going, yeah, yeah, sure, generatedFunc is like createFunction, yeah, got it.
[00:09:59]
And we've all been there, and if we get this bit, close your book, it's so naturally. This is actually the cause of underlying confusion. So let's try and answer a few more ways. When I ran createFunction at one time I went inside and I created multiplyBy2. When I actually did that createFunction execution context it was created by calling it I lose access to anything inside of here.
[00:10:23]
Unless, hold on, let's ask map, can I still run the function definition of multiplyBy2 back in global?
>> Speaker 6: Yes.
>> Will Sentance: Yeah, how come? What can I use? What label can I use?
>> Speaker 6: You can use generatedFunc.
>> Will Sentance: I can use generatedFunc, because generatedFunc is the result of one-time running a createFunction, that it turned out the definition of multiplyBy2.
[00:10:41]
How many more times do I have to? [LAUGH] Which way should I say it next? So to be clear everybody, if I'm running generatedFunc, I'm running the function that was born as.
>> Speaker 6: MultiplyBy2.
>> Will Sentance: If I'm running generatedFunc what? Someone say created, I heard the word createFunction. If I'm running generatedFunc, I'm running the function that was born as what?
[00:11:03]
>> Speaker 6: MultiplyBy2.
>> Will Sentance: GeneratedFunc is the code that was originally what?
>> Speaker 6: MultiplyBy2.
>> Will Sentance: Exactly, definition of multiplyBy2. GeneratedFunc, does it have a connection to createFunction?
>> Speaker 6: No.
>> Will Sentance: No, did it get created or sort of get created by createFunction? Yes, but that was it, and we moved on.
[00:11:23]
Okay, so, if I'm running generatedFunc here, I'm gonna create, everybody, a brand new?
>> Speaker 6: Execution context.
>> Will Sentance: Excellent, Peter. Everyone else a brand new?
>> Speaker 6: Execution context.
>> Will Sentance: Very nice, there it is. Okay, and here's why it's really confusing I think. Let's go into it.
>> Will Sentance: Our arguments 3, what's the placeholder?
[00:11:46]
What's the parameter? Dan, that's waiting for that 3?
>> Dan: Num.
>> Will Sentance: He's spot on, but here's why this is doubly confusing people. Where did Dan have to go, to figure out what the placeholder was? He had to go back into createFunction. Visually as a developer if you're back in and yet is JavaScript doing that 100% no.
[00:12:06]
But how damn confusing is that that Dan had to go back up to create function and see more of it and he will saved that? But that's not where it's actually saved. That line there when we ran createFunction ran that code, which was by the way create functions global saved in global memory.
[00:12:22]
Even when it ran create functions didn't go backups create function. The thread never goes back up, it didn't have to because when it say you create functions that start, it saved all the code in memory. That's where it went and grabbed the code from to start running it.
[00:12:34]
And then it created inside of createFunction multiplyBy2. And it literally saved the code of multiplyBy2 including the parameter name num, creating parameter name num into that execution context, local memory. And then he grabbed it and returned it out into global and stored it under generatedFunc. And it's into memory where we go and grab the code of that function that we had when we run generatedFunc.
[00:12:58]
But the problem is, we don't get to see that because we don't get to see visually that code multiplied by 2 stored over here. So we have to visually as Dan did, go back up, but JavaScript is not doing that. It has no interest in createFunction. But it's pretty doubly confusing that visually to figure out how the generatedFunc is working, we have to go back into createFunction.
[00:13:23]
But only in terms of our perspective, our developer looking at it, JavaScript is not doing that. Okay, so well done to Dan, exactly. Let's now do number 2, which is 3 by 2 which is 6 and we return that out into result. So it's the evaluated result into result.
[00:13:46]
And there it is. Wow, why did we do all of this in the first place? Let's have thumbs over now on what fundamentally people, I promise you this isn't one of the ones where you're like I roughly got it, this is the mission-critical part of closure, so it's okay.
[00:14:06]
It's also not like, this is an easy thing. I promise you, I've seen too many developers with ten years' experience not really have the precision of the execution down here, okay? You lost me, I'm clear, clarifications? Everybody, thumbs out, I promise you, it's good to have clarifications on this.
[00:14:22]
>> Will Sentance: Okay, promise, okay, all right promise, promise?
>> Todd: [LAUGH]
>> Will Sentance: All right, so one thing I will say is this, why did I save a nicely semantically that means kind of meaningfully named function inside there another function, only to then return it out, giving it a really bad name out and use it globally?
[00:14:45]
One will just to find it globally. What I possibly have done it this way round. Is gonna turn out people. That, saving a function, declaring storing a function inside the execution. Context of running another functions of saving inside its local memory inside another function. When that function gets returned out, it gets the most powerful property bonus feature of JavaScript that we can ask for.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops