Lesson Description

The "Function Scope Q&A" Lesson is part of the full, JavaScript: The Hard Parts, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Will answers questions related to function scope and what other data can be reference by the inner function through the "backpack".

Preview

Transcript from the "Function Scope Q&A" Lesson

[00:00:00]
>> Will Sentance: OK, so let's do thumbs on this, and do not fear, we are going to learn what the heck is this bond called? Can I get manual access to this data on this function, it's stored on this function? Maybe I could go newFunc.backpack.counter. Maybe. But let's start with thumbs on this core notion that when I define my function outer, and then when I call that function, inside of that called outer, I defined a new function add1, I defined some data counter is literally now 0, live in that execution context.

[00:00:45]
I then returned out that function, add1, stored it in a new label, newFunc. When I run it, I'm not just creating a local memory, because when I define my add1, I didn't just save the function add1, I saved the function add1 and a little hidden link to its surrounding stored data, its surrounding live local memory. Not counter could be zero, not declaring counter is zero in the text, but literally counter is 0, saved in the computer.

[00:01:23]
And then when I returned out that function, when I returned out this add1 function, let's actually make it clear that it's, when I returned, oh no, no, no, when I returned out that add1 function, it brought with it on its back. Here we go, on its back, a little collection of all the surrounding live data. And now newFunc is not just the add1 function code, but with a store of the surrounding data from when it was born.

[00:02:02]
And so when I run newFunc with friends and I create that local memory, and I reference counter, and it ain't there, before I just go down the call stack into global and give up, I first look on the backpack of my newFunc, and there I have the stored data that I literally pulled out of my running of outer attached on the back of add1. I run newFunc again, and this previous execution context is local memory would have gone if counter had been defined in here, gone.

[00:02:36]
I start again with a new call to it, counter plus plus, check local memory, ain't there. Don't panic, don't go to global first. Head to newFunc's hidden store of persistent data from when it was defined and born. Find counter is now indeed plus plus already 1, and add another one to it. Suddenly my regular old functions have two types of memory. The one they create live when they run, and the one that sticks around in between invocations, and is only available to it.

[00:03:17]
Inside of that function, this ain't global, this is data that is created, this is a memory that is only available to that function, but unlike the one that gets rewritten every time, this one sticks around. Let's have thumbs, you lost me. I'm clear, I have clarifications. OK, Matt's clear, we've got some great clarifications coming, Tenzin's clear, Chris has got a clarification. Michael's got a clarification, Joe's got one, let's start with, Ryan's got one, let's start with Joe.

[00:03:51]
Uh, OK, um, so do you want extra time, Joe? What's up? Do you want some extra time? No, no, it's quite all right. I had it phrased, and I'm just trying to make sure I still have it. So when we return, add1 from the outer function context, right, is it returning everything that's like, quote unquote, a sibling to add1? Like if there were other functions in that body, what a great question. Or is it only keeping track of data that was within its execution context at the time that is actually called or referenced inside of that function.

[00:04:25]
Oh, it feels like there are a couple of different questions there, so the first one, let's come back to in a second. I thought the question you were asking is, for example, if I declared inside of outer, let's say another counter, and set that to 5. Inside of add1, I didn't reference another counter, so I had another counter is 5, and inside of add1, I didn't ever ref I only referenced counter plus plus.

[00:04:54]
Would it make any point to have another counter's data also in this backpack? Can I ever access it from anywhere else? Uh uh, it's only ever accessible from the function that I returned out that has the access to this hidden persistent data, therefore, JavaScript smartly, literally looks at the body of the add1 function and goes, what can you ever reference, and here's the thing, it looks at it at definition time and says, uh, what do you ever, make what identifiers, what labels do you ever make reference to?

[00:05:28]
It's counter, you can have 100 other things in here. If they're not referenced in that function, when that function's returned out, they are what they call garbage collected. They are removed, deleted, forgotten about. But that's because the only place we can ever access this data is by the very function that we've returned out and held onto the persistent data. So JavaScript can do a little read of the details of the add1 function and go, I'm not going to save everything, there's no point.

[00:05:57]
Only save the stuff that is relevant. Uh, great question. Joe, if your other question was, what about if there's other, what if outer is being called inside other functions, could I return out multiple levels, I'd say go play with it, but also this is a chain. Like many of these things, you're going to have a chain up, and so the answer is yes, but go play with that in terms of if this is being embedded in multiple other function calls.

[00:06:26]
Uh, let's go to Michael. Uh, that was actually both of my questions, but basically, I guess to summarize that, it's just if it has a dependency on something that is outside of it, it will keep a reference to that memory. Yeah, that's exactly right. And if you're very familiar with, you know, programming, you might be like, oh, OK, well, you know, fine. But if you really think about it, it is very counter how we think about execution.

[00:06:53]
It's vital and really powerful, and it's going to turn out, especially if this function that's being called, is being called way later because you've asynchronously brought it back in to be called when some data from an API returns, you, the ability for that function to hold onto its surrounding initial backpack of data is a really powerful thing, especially in an asynchronous language, but in its very pure core, JavaScript is a very do this, then this, and when you hit running a function, do all the stuff inside of it and then forget about it, besides the return value.

[00:07:34]
And yet it doesn't, because if you return a function out of another function, that function gets this special backpack of persistent data. And I don't think there's anything that's used more profoundly across JavaScript than that ability, because we'll see, think about the module pattern, the idea that you don't want to have in a 3 million line codebase, uh, anyone using the word result, the label result, because your colleague from 17 years ago used the label result.

[00:08:03]
So you want to have labels like result because they're useful, but not have it pollute the global namespace. Well, you bet you know how it's all done, because it can't just be only available when you call a function, and then when you exit the function, all the data's forgotten. You bet you know how it's done in vast, complex backpacks. The module pattern, in fact, is just storing stuff, well, we'll see all this.

Learn Straight from the Experts Who Shape the Modern Web

  • 250+
    In-depth Courses
  • Industry Leading Experts
  • 24
    Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now