Check out a free preview of the full JavaScript: The Hard Parts course:
The "Closure Exercise, Part 1" Lesson is part of the full, JavaScript: The Hard Parts course featured in this preview video. Here's what you'd learn in this lesson:

Will walks through an example of calling a function in the same scope as it was defined.

Get Unlimited Access Now

Transcript from the "Closure Exercise, Part 1" Lesson

[00:00:00]
>> Will: We just started encountering some mysterious behaviors by JavaScript there, right, some mysterious behaviors. We're gonna see how all of those play out. They're all gonna rest on this notion we saw here. So here we go. Before we do that, we have to understand that we're gonna encounter this scenario here.

[00:00:20] Gonna encounter this side here. Calling a function in the same scope as it was defined, okay. This is gonna start to answer, I think it was Shelby's question or it was Katy's question about, about. Well, hold on. What if I don't find the value, the variable I'm looking for inside my local memory?

[00:00:45] Where do I look next? We're going to see that play out here, and we're gonna discover way to find your functions fundamentally determines what your function has access to when you call the function. That sounds pretty obvious right now. It's gonna create a level of profundancy we can't even yet imagine, all right.

[00:01:10] So lets walk through this. And as ever, I've not cleared the whiteboard first unfortunately. So I'm just going to boldly go ahead and say, Muhammad, can you speak very slowly and start walking through what we're doing, Muhammad? Not literally slowly, that would be weird, but go ahead, Muhammad.

[00:01:30]
>> Muhammad: We are declaring a function with the label outer.
>> Will: Declaring a function with the label outer, excellent. And where are are storing it, Muhammad?
>> Muhammad: In the global memory.
>> Will: In the global memory, perfect. Thank you so much for speaking slowly. There it is, it's a whole function definition.

[00:01:53]
>> Will: There it is. But I do these little fs in my function now, because if you look at Chrome dev tools, when you console logger function now, in the console it'll actually do a little fancy f before the function. Interesting, I don't know why. All right, so next line that we call, Lindsey?

[00:02:11]
>> Lindsey: When you're calling the function outer.
>> Will: Calling function outer. Everyone together. Loud, clearly, and emphatically, when we execute a function we create a brand new-
>> All: Execution context.
>> Will: See, it feels good, right. Feels really good. There it is. The new execution context. Draw it about this big.

[00:02:33] There it is. In which, so what execution context reminders means is outer is some functionality that we want to run. We wanna therefore go through it line by line. So we've gotta pause our thread, we only got one thread from running any code further down, and take it inside the function.

[00:02:55] That's the left hand side here. So remember, we're in the global execution context. We're gonna go inside the local one for outer, the thread's gonna go inside there, out from global, into outer. And we want to store in outer any functions or variables that get announced inside of outer's code.

[00:03:16] Well we need some space to do that, so we do them in the local memory. This is the execution context. When we call a function, we push it to the call stack. A stack of calls, to functions. In to outer we go. And what's the first thing we do inside of outer, Andrew?

[00:03:38] We're calling out, what's the first thing we do inside?
>> Andrew: Let counter equal zero?
>> Will: So we declare counter and initialize it to zero. Counter is zero. That's freed up a little bit of memory for the number zero and given it the label counter inside of the code outer.

[00:03:59] Not out here. Let's be clear, if I have a console log counter out here, there ain't no counter. Only inside of the code outer. All right, what's the next line inside the code outer, Amine?
>> Amine: Declare a function, increment counter.
>> Will: Good, and store it in?
>> Amine: Local memory.

[00:04:18]
>> Will: Local memory. Excellent, Amine. Thank you, and there it is. Increment counter stored in local memory and it's the whole function definition. Let's not forget, if I had a console log it, I would see function. Increment counter, counter plus, etc. Now, but what do I do next, Katie?

[00:04:38]
>> Katie: We execute that declared function.
>> Will: Good, we execute increment counter. And therefore, everyone together, we create a brand new?
>> All: Execution context.
>> Will: Yeah, exactly, so I can really pick on my son, Dominique, saying it. I shouldn't have said it into my mic so loudly. Execution context, exactly.

[00:04:59] There it is. Which has it's own, has it's own little baby local memory. Tiny little local memory for increment counters, execution context. There it is. Local, and remember this is also known as a variable environment. A variable environment. A variable environment. Posh name for the memory. Okay, so call stack.

[00:05:26] Lindsey, what happens when I a call stack?
>> Lindsey: We push on the increment counter.
>> Will: Yes, the code increment counter There it is. It's now on top of our call stack. We're a few layers in now. And what's the first sign of code inside increment counter that we encounter, Lindsey?

[00:05:44]
>> Lindsey: Counter++.
>> Will: Counter++. Now, where do I go looking for that counter first, Lindsey?
>> Lindsey: Locally.
>> Will: Locally, exactly. Partly because or so it might seem because lowest of my call stack, increment encounter is where I look for stuff first cuz that's where I am. I'm there. So I look locally.

[00:06:10] Do I find counter, Lindsay?
>> Lindsey: No.
>> Will: No, so do I error? No, I don't error, it's not there but where do I look next?
>> Lindsey: In the outer.
>> Will: Exactly, I look down my, hold that thought looking down the call. So we're gonna see it's not quite that, but it feels like I look down my call stack, right, and what do I find the next level out?

[00:06:33] But, Lindsay.
>> Lindsey: A counter.
>> Will: What do I do with it?
>> Lindsey: I add one to it.
>> Will: Increment it to one, perfect. There we go, and now increment count is execution context comes to a close. Comes to a close, it's done. And increment counts is called, Lindsey, on the call stack gets?

[00:06:58]
>> Lindsey: Popped off.
>> Will: Popped off, and back to outer. Anymore code to run in outer?
>> Lindsey: No.
>> Will: No, so outer execution context, Lindsey?
>> Lindsey: Gets popped off.
>> Will: Popped off, and outer is also done. I don't see that's particularly clear is it? Well, all right. All done.

[00:07:22] Well what do we know? We said where we define our functions determines what variables our function has access to when I call the function. Well, I defined increment counter, and it immediately had a rounded count for zero. I then called increment counter, and what do you know? While I didn't find counter inside increment counter, I looked one level up and where, there I found it.

[00:07:46] Counter is zero, it feels very okay, this is how JavaScript works. But what if I called my function outside of where it was defined? So right now, we've got no problems here. I'm defining my function, and what do you know? When I call it in the immediate same scope in which it was defined,

[00:08:10]
>> Will: The encounter is not available in the local memory, but look down the call stack, look one level out, there's counter, hurray. We have a problem. But what if I call this function out here, not where it was defined, but outside of where it was defined? What if I ran it somewhere else, outside of where it was defined?

[00:08:31] We may already see that we're going to have some serious issues here. But is this gonna even work? Can I even do this? Can I even call increment counter outside. Will this even, will this work, Kara? Can I refer to, have we defined increment counter? Does this work?

[00:08:48] This is my, the answer's no, question voice. It doesn't look it's gonna work, is it? Because increment count was defined inside of outer, not in global memory. So I was saying we're gonna get something very special is gonna happen when I call my function outside of where it was defined.

[00:09:07] But how do I even do that, Muhammad? How do I even call a function if it was defined inside of outer? How do I even call it out here, Muhammad?
>> Muhammad: You have to return it so that it's able to be called outside.
>> Will: Yeah, let's see that in action.

[00:09:22] There is a way to run a function outside where it was defined, return the function, and assign it to a new variable and then call it by that variable and then very nice.