Check out a free preview of the full The Hard Parts of Functional JavaScript course
The "Outer Function" Lesson is part of the full, The Hard Parts of Functional JavaScript course featured in this preview video. Here's what you'd learn in this lesson:
Will demonstrates how to assign the return value of the inner function, to an outer function, and give it a global label. On the back of the inner function comes its entire surrounding local memory.
Transcript from the "Outer Function" Lesson
[00:00:00]
>> Will Sentance: I heard some really interesting things that people were talking through there. We're gonna save that out of function we're going to call it we're going to return out the little baby increment counter function from inside out into a new global label new function. And we're gonna call it by its new global label and some really interesting stuff is gonna happen.
[00:00:16]
Stuff that's going to give our functions superpowers. In a special way. So here we go line one Andrew you're up what are we doing in line one?
>> Andrew: Declaring a function.
>> Will Sentance: Declaring a function. Technical communication means total precision and completeness. Andrew take it away. Declaring?
>> Andrew: A function to outer.
[00:00:35]
>> Will Sentance: Exactly declaring a function named outer. There it is, thank you to Andrew for his patience with me. Sam, next line, left hand side first.
>> Sam: Declaring a new label.
>> Will Sentance: Yes well done, new label, new function exactly. We do not know yet what to store in it, because we've got to go ahead and run what Sam?
[00:00:57]
>> Sam: We need to run outer. So-
>> Will Sentance: Perfect.
>> Sam: New place.
>> Will Sentance: Outer folk. Let's have our cool start going here. There it is global in the bottom we add outer. Next. Bubenesh we're executing out so we create a new?
>> Bubanesh: Execution complex.
>> Will Sentance: Execution complex thank you Bubenesh we appreciate it.
[00:01:18]
That's very on point. Into what we go. And we immediately, no inputs no arguments. So instead in local memory, Jasmine, we immediately assign what?
>> Jasmine: Counter to zero.
>> Will Sentance: Counter to zero, excellent. Michael next line, I do this thing where I give the same person the same question every single time without thinking about it, Michael next line.
[00:01:48]
>> Michael: We create a function called the increment counter.
>> Will Sentance: Increment counter. Jasmine, did I ask you for zero last time? I didn't ask you for increment counter that's so interesting. What is it? What is going on in my mind subconsciously that does that, that process probably, what ever that means.
[00:02:05]
All right, ignore encounter is saved, we are not going to use it inside though. Instead, we are going to take its code or if you remember from our heap piece we take the label to its under the hood stored function. Wait sorry, address if it's under the hood, stored function and table but with us for our purposes, take the code of increment counter.
[00:02:30]
We're going to see what, what are we going to do Jasmine? We're not going to return. We're not going to run increment counter, we're going to?
>> Jasmine: Return increment count.
>> Will Sentance: Return increment counter. So it's going to say return increment counter we use that to look up increment counter it's the code of increment counter without a label and we take it Jasmine and we return it out into?
[00:02:54]
>> Jasmine: New function.
>> Will Sentance: Into new function she's spot on. And it we used to be called increment counter. It's not called that anymore. I'm just putting it here so we know it used to be called that. And there it is, and its only code is counter++. And our execution context here, everybody, is what?
[00:03:12]
>> Class: Gone.
>> Will Sentance: Bumped off the call stack, exactly, removed. We pop it off, we pop it off the call stack.
>> Will Sentance: There it is, gone. And we're out to global where our new function is now our new global label for the function that was borne inside of outer as increment counter.
[00:03:33]
Let's run it people and let's see what happens. New function is called brand, yeah, everyone together, brand-new?
>> Class: Execution costs.
>> Will Sentance: Thank you, that energized me, after my silly lack of enthusiasm. There it is, it goes on the call stack. A new function is added on the call stack.
[00:03:59]
We go into it, nothing in local memory assigned. Instead, we hit immediately what line, Jasmine?
>> Jasmine: The counter plus plus.
>> Will Sentance: Counter plus plus, cuz new function is a functionality formerly known as increment counter. Where, Jasmine, do I look for counter first?
>> Jasmine: Local context.
>> Will Sentance: Yes, excellent, thank you, in the local execution context.
[00:04:23]
Again, same question to you again, anything there?
>> Jasmine: No.
>> Will Sentance: No. Now, where would everything, every intuition we've thought over the years suggest, given we first check top of our call stack new function where we would look next Jasmine, every sort of intuition we have about I run my function here.
[00:04:47]
I have access to stuff outside of where it's running where would I say I can go and look for counter next?
>> Jasmine: Maybe we think to look in outer.
>> Will Sentance: We might think look in outer but outer's off the, that execution context is shut down. It's off that cool stat, therefore.
[00:05:03]
[SOUND] We can't take our thread back in there that's done our threat of execution went in, came back out, and it's gone. And we're now inside of new function. So we're running a new function in global. So Jasmine, where might we look for counter?
>> Jasmine: Global.
>> Will Sentance: In global.
[00:05:22]
In theory, sounds right to me.
>> Will Sentance: This line is not very good. Is countering global, Jasmine? It's definitely not.
>> Will Sentance: It kind of gets old [LAUGH]. No, very sad!
>> Class: [LAUGH]
>> Will Sentance: Very sad! By the way, what a problematic language design that let's this happen. This feels like a bad language design obviously.
[00:05:55]
Given that this is not the core focus of this talk, we wanna use this. For a very powerful feature, I'm not gonna dwell on this, but I'm not gonna sort of let us suffer for too long. Instead, I'm gonna tell you about a powerful thing that happens when I return a function out of the running of another function.
[00:06:20]
Give it a global label and run it by its new global label. Something very special happens. I do not just get the code of the increment counter function returned out into new function. I bring with my function code something else. On the back of this function comes,
>> Will Sentance: [LAUGH] On the back of this function comes, its entire surrounding local memory as the function gets returned out, gets returned out into new function.
[00:07:06]
It brings with it attached on to it on the back of the function. And here it is on the back of the function it's a little backpack as the function gets pulled out, it pulls with it on its back. The surrounding data from when it was born and look at that.
[00:07:26]
There is counter is zero attached to, and we'll talk about whether there's any more official name than backpack. I will tell you this after somebody saw this talk and wrote a blog post about it has 50,000 likes, meaning this term is ever more popular may into the spec of JavaScript, never, but maybe there it is attached on the function, meaning Jasmine, take a shot after not finding counter in new functions, immediate local execution context, you rightly said the local memory there.
[00:08:04]
Before I look to global, might there be somewhere else and you can use the word. You can say the word it begins with b and ends back. Jasmine is there somewhere else that you think that JavaScript's going to take its lookup journey to before it searches global for counter?
[00:08:22]
>> Jasmine: You might look in new functions back pack.
>> Will Sentance: You would look in new functions back pack. Thank you so much Jasmine. She is spot on, off we go into new functions back pack, here it is, and what do we find there, Jasmine, we find counter is?
>> Jasmine: Zero.
[00:08:44]
>> Will Sentance: Counter is zero, she's spot on, what do we do to it, we increment it, Jasmine to?
>> Jasmine: One.
>> Will Sentance: To one. This execution context gone. We are not gonna erase it, we're gonna add it back on because we're gonna run new function again. We're gonna talk all about this backpack in a moment people.
[00:09:08]
It's super powerful.
>> Will Sentance: Everything in the local memory there's nothing here but everything as always is deleted, it's only temporary. Run new function again. Brand new Anna, brand new what?
>> Class: Execution context.
>> Will Sentance: Excellent everybody but Anna as well. Excellent Anna into we go when they turn up the audio for your mics and it's just Bubenesh saying execution context.
[00:09:36]
We find in as next call to new function counter plus plus, Eric where do I look for counter first, by the way, just to be clear, this is a new new function execution context on the call stack. I erased it and put it back on again. And where do I look first, Eric?
[00:10:00]
>> Eric: First we're going to look in the local execution context.
>> Will Sentance: Fantastic. Do I find counter?
>> Eric: No counter there?
>> Will Sentance: Where do I look next? Don't use any fancy terms.
>> Eric: We're gonna go to the backpack.
>> Will Sentance: We're gonna go to the backpack, where we find counter is?
[00:10:14]
>> Eric: One.
>> Will Sentance: Wow, we find counter is 1. We increment it to?
>> Eric: 2.
>> Will Sentance: 2,
>> Will Sentance: Immediately, people, you might be able to see this has supercharged our functions. Functions are just two things. Well, as for now let's say two blocks of code, which when run, they get to walk through the code, the thread and a temporary memory bundled up just for the function of that time.
[00:10:45]
This enables our functions to have two types of place to store data, one temporary for their single execution, the single running and one permanent persistent, that's there as long as the code of the function is saved. Add function's not just code anymore, it saves code under the label new function that was originally increment counters code plus persistent data attached to it that we get access to by making reference in new function borders increment counter to something that's not in local memory.
[00:11:21]
So we jump out and look in the backpack and as long as when we birthed when we created the now known as new function. Function originating from encounter. We had around it in local memory, save counter is zero, that gets pulled out on the back of the function into new function.
[00:11:41]
And there it is attached, there it is attached people. So I'm going to. [SOUND] I'll address this one more time new function's definition, its code, its saved code now has a hidden link. Hidden, well, that's why I got to tell you a few few more important things about this before we move on to thumbs.
[00:12:05]
How is this permanent data here attached to the function? Well firstly, we can't get to it directly. I can't go new function in global, newfunction.backpack.counter, this is not possible. I can't even go newfunction. Official name for it dot counter as they were getting into it, it is absolutely they call it private to that increment counter now known as new function.
[00:12:38]
Function call, we can only get into it by running new function, not finding something we reference in the local memory and jumping out to the backpack. The backpack kind of inserts itself before we go down to looking in global. Don't get me wrong the backpack in global in the sense that it's attached to a function that saved in global.
[00:12:58]
But global really means I can access the name for that data when I'm in global execution context, I can't access this data, it's hidden, it's protected. Well, how is it protected? Well, as soon as the function increment counter was saved inside the running of outer when outer was on our call stack earlier inside that execution context a thread was running through.
[00:13:20]
As soon as increment counter was saved. It immediately got a link to the surrounding memory. Immediately, to the whole surrounding memory. That link was stored on a property square bracket square bracket, two square brackets. Scope square bracket linked to this running memory. It'll copy just a link to where it was literally stored.
[00:13:41]
When I returned the function, out, I pulled out on that link all the data with me attached to the function. Still got that scope property, there it is. How did the lid-
>> [INAUDIBLE]
>> Will Sentance: I mean, [LAUGH] the lid has returned!
>> Class: [LAUGH]
>> Will Sentance: Charmed, amazing, there it is.
[00:14:01]
I was about to start shaking it again then I thought, well, that's. Okay, meaning as I say, whenever new function runs and it doesn't find counter's local memory, it goes through its definition looks into its hidden scope property, in other words into the backpack and finds counter. Because counter was there when it was born and when it got returned out, the code of increment counter from running outer.
[00:14:23]
We ran outer we returned that increment counter from it being creating it inside out and we returned it out into new function and we run new function and it doesn't find counter the local memory and looks to new functions backpack stored on the scope property. I want to do thumbs but I want to probably tell you a few more pieces about this backpack first.
[00:14:46]
Firstly, it's really optimized, Java Script makes the link on the saving of increment counter inside of outer to the surrounding local memory, everything in there, the link to the whole collection, everything, there is a link to where this all stored in memory, but on returning out that function.
[00:15:07]
Normally when you finish running a function, what's the only thing we hold onto, Sam? When I finish running a function, return out three. All the other stuff in the local memory, do we hold onto it?
>> Sam: No.
>> Will Sentance: No, we automatically garbage collect it. Why is it called garbage?
[00:15:20]
It's called garbage because we can't access any of that data by its name anymore. So there's no point it being there. We automatically collect it. It means it automatically gets deleted by JavaScript.
>> Sam: So weak reference.
>> Will Sentance: Sure. This is absolutely instead here, we rely on when we return out this function JavaScript is going to hold on to all that surrounding data in the backpack of the function, but hold on.
[00:15:55]
What if I say maybe 10 different things in this local memory. I return I increment counter into new function run new function. I've got 10 things in this local memory besides counter. What's the only thing Alex, inside of new function for me was increment counter what's the only thing I refer to Alex?
[00:16:17]
>> Alex: Counter.
>> Will Sentance: Counter. So if I've got 10 other things in this backpack, can I get access to any of those? No, I can't access anything that's back. I can't go, newFunction.scope.counter, I wouldn't want to. I want it to be preserved and protected for the running of the function.
[00:16:32]
Meaning, I know on the return sorry. Better, JavaScript knows, on the returning of incrementCounter to newFunction, it already knows what that function could ever end up needing or accessing. And so it optimizes what gets pulled out in the backpack once we exit outer and delete everything else in the local memory.
[00:16:56]
If it's not referred to, delete it.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops