This course has been updated! We now recommend you take the JavaScript: From First Steps to Professional course.

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

Finishing up the scope exercises with students, Bianca examines scope: inner function accesses both inner and outer variables and retaining access to variables from the outer and inner scope. Bianca takes questions from students.

Get Unlimited Access Now

Transcript from the "Scope Walkthrough, Part 3" Lesson

>> So our next one says an inner function can access both its local scope variables and variables in its containing scope, providing the variables have different names. Okay, where did we leave off? Who's the next willing volunteer? Who signed up?
>> I remember close to [INAUDIBLE].
>> Yeah.

>> I mean, maybe it was me.
>> Okay.
>> So we're setting our name variable to outer.
>> Yep, and then what happens next, Michael?
>> We are creating a variable fn, setting it equal to a function.
>> Yep, and then Aisha.
>> Function is invoked.
>> We invoke the function.

[00:00:50] We hop back up into the body of the function, what happens next?
>> We enter the body array, saying that innerName is equal to inner.
>> Yep, so we set innerName to the string inner. And then Josh what happens next?
>> Set ACTUAL to innerName plus outerName, inner name is inside this function so we can set that outer name is parent scope, so we can set that as well.

>> Yep, we have access to both of those, so no errors. Jenny, what do you think it'll say?
>> It should say both of them, inner and outer.
>> Like that.
>> Yeah.
>> Inner or outer, but it says, [LAUGH] cool. All right, any questions about that? It seems reasonable.

[00:01:47] Cool. So the next one is, between calls to an inner function, that inner function retains access to a variable in an outer scope. Modifying those variables has a lasting effect between calls to the inner function. So this is similar to what we were doing before, except when we were initializing the function twice, in the function and the numbers were resetting and the initial values were being erased.

[00:02:14] This is similar to that. This is the solution to that problem. Bryan.
>> So [COUGH] outerCounter is declared and assigned 10.
>> Yeah, so we just initialize this value at 10, great. And then Dan?
>> Declaring functional variable, assigning it function.
>> Yep, and then we call the function, get to this function body.

>> Sure, within the function body, we take outerCounter and increment its value, so outerCounter becomes 11. And then we sign ACTUAL, the value of outerCounter, so ACTUAL becomes 11 as well.
>> All right, awesome. So just to recap, call the function, we have access to outerCounter cuz it's in our parent scope.

[00:03:14] The value is 10, we're adding it to 1, and then we are reassigning it to outerCounter again that lives in the parent scope. We're setting ACTUAL to outerCounter. And so we think ACTUAL will equal 11. Next thing that happens is this function gets invoked again. So we hop into this body of the function, just like we mentioned before, everything in here gets reinitialized for the very first time.

[00:03:38] However, we still retain access to our outer scope. This is the same scope, okay? Cuz this function was called once. So we have one parent function scope. We called this function the first time. So we created that scope, it ran through, and then it gets thrown away. Once it's done, it gets thrown away.

[00:03:59] And then we call it again, and we created another scope, okay? So in this process we've gone through three scopes, if we don't count what's going on here. So we have these parent scope that was created, we run the test, and then two scopes from these two function calls here, okay?

[00:04:23] Everyone following that? Okay, so who was next actually? Kevin? You always get to be on the tricky one.
>> Incremented outerCounter was preserved cuz it was outside? So, it's 11 +1, so we get to 12, so actually equals 12.
>> Yep, so because we incremented outerCounter in the parent scope and the previous call, it is 12.

[00:04:58] It's 11, we increment by 1, ACTUAL is now 12. Cool, any questions? Yeah.
>> So what if online 153 had the word var before outerCounter? Cuz my understanding is if you like using var then it's kind of reinitializing it and that would over write the outer scope one.

[00:05:32] But that pi still wouldn't change it here, right, because it would still be adding, it would be setting 12 to that new outerCounter, and then that would reset to ACTUAL. Does that make sense?
>> So the question is when we put var here does that change what happens?

>> Right.
>> Let's try it. Which one was that one? Between calls. This one. World's tiniest font, okay. Yeah, that's failing to save.
>> So that did break something?
>> Yeah, so it did change it. Let's erase it, make sure you-
>> Do you know why it changed it?

>> It's because the variable it's initializing another variable in that scope, instead of referencing the parent variable.
>> So JavaScript doesn't throw errors or anything when you try to reinitialize a variable that's already been initialized?
>> It does with let. I can use let and const obviously.
>> So let will throw an error there.

>> I think so, let's try. Yeah.
>> What was the error it threw when you call var before?
>> It says outerCounter is not defined.
>> When you call them var though?
>> When I called it var it just, so it will pass. If you do this, okay?

[00:07:12] var, so outerCounter equals outerCounter. I wonder what it is.
>> Should pass the first but not the second?
>> So it goes through and refer to itself or anything?
>> Let's put a little debugger here and check it out. Okay, so because this is undefined and you're adding.

[00:07:41] So if you add 1 plus undefined, Gives us no number, yeah. Cool, beautiful. All right. Next one is the rule about retaining access to variables from an outer scope still applies even after the outer scope, the outer function call that created the outer scope has returned. I'm gonna read that one more time.

[00:08:19] The rule about retaining access to variables from the outer scope still applies. Even after the outer function call that created the outer scope has returned, okay? I'm just like what? [LAUGH] Well, let's see it in action. Where did we leave off?
>> Was it Chris?
>> Sure, the first thing that will happen is defining outer function which declares the function.

>> Yeah, so the very first thing is we create this huge function. And then what's the next thing that happens?
>> Then we declare a variable outer function.
>> Where, what line?
>> 164?
>> We just did that.
>> Okay.
>> Yeah.
>> Hold on. And then we set counter in outer scope to?

>> Well, this function actually hasn't been called yet.
>> Yeah. Do you see it being called anywhere?
>> No.
>> Yeah. But I like your enthusiasm to go above and beyond the rules and JavaScript. [LAUGH]
>> Also then, so then it just runs in are incrementing.
>> No, so this whole function here it's a big one.

[00:09:49] Yeah, you see. I try to have this like rainbow thing so you can, it's really colors. So, you can see if they match. So this is green, so all of the yellow ones are inside the green.
>> I think it gets really washed out on there.
>> Yeah I try

>> You can see it now though yes actually,
>> Yeah,it's a nice plugin for VS code, rainbow indent. Okay, so this is a big function. So obviously what happens next then.
>> We run expect
>> If we run this as expect, we expect window.retained inner function to equal undefined.

[00:10:36] What do we think? So this is referencing this I guess What do we think about that? Seems reasonable.
>> It should be undefined.
>> It should be undefined, right? Because we haven't run the body of this function. Nothing here has done any work. And so you can't have a reward such as a value assigned when there hasn't been any work done.

[00:11:03] Seems fair, okay, so then we're gonna run the outer function So where did we leave off? Jamie was to you. So we're gonna run the outer function. So we're gonna come back up here.
>> Yep, so then we're setting variable counter inner and outer scope to equal 10.

>> Then Mike, what happens next?
>> Then we set a new variable innerIncrementingFn declaring that function and then right after invoking it.
>> Awesome, Aisha?
>> We go to the declaration and
>> Run the function right.
>> Run the function.
>> Yep. So you run the function out to mirror what is gonna happen in this function.

[00:11:59] This is really similar to the last.
>> Inside of the body. Then we doing CounterInOuterScope, InOuterScope plus 1
>> Equals 11 actual it's 11.
>> Yeah, set actual to 11. Who remembers what happens next is the same example. What is this actual gonna equal?
>> 12.
>> 12, okay, then we do something a little funky Josh, you know what we're doing here?

>> You're setting property on the window, you're incrementing function.
>> Yeah, so we're click creating a global variable, a global property on the window object and assigning to innerIncrementing function, which is this function here. Cool, so then we exit. We find ourselves here. Where we say expect{window.retainedInnerFn} function.

>> Line 178 inner incrementing function doesn't have to have the parentheses right after or?
>> If not necessarily, that's if you're gonna invoke the function. In this case, we're passing a function. Well, in this case, we're assigning the function to basically it's like saying this. Oops, and saying like saying, you're creating a variable, and then you're assigning it.

[00:13:44] Like this. That's essentially what it's doing. See that? Okay.
>> So if we were to put on the parentheses, that would be running it in the window.retainedInner function, it would take the result of that function.
>> Yeah so if we ran it, it would be whatever this returns, which doesn't return anything.

[00:14:13] It would just be equal to undefined and that's not helping us. So we really just wanna return that function because we wanna have access to it globally. Okay so that we expect it to be a function. Yes, I believe that. Now we're calling it like you were kind of, talking about before, but we're calling it out here in the parent scope.

[00:14:42] And we have access to it because, it's on the window object which is global in the browser land which is where I reside in browser land.
>> The chat is asking about the indent, the dots in the indents that a plugin or something you can do in VS Code?

>> Yeah, I think it's just a setting where it shows it the dots mean it's a space and then if it has a like a little arrow, it shows that it's tab. But I kind of download just every plugin for VS Code and so I have a bunch of them I don't know which ones which.

[00:15:22] And I don't recommend doing that because my VS Code has been freezing lately, and I'm not sure which plugin is killing it. So, but I like the rainbow one, the rainbow one might even be including the dots. So now we're calling return inner function, what happens next? So what happens after you call a function every time?

>> Well, it's gonna have to go through the body of it.
>> Yeah, so we have to go find the body of that function, which is here, right. Because we assigned it, but really it's here, okay. So what happens. I don't know if it returned the 12 or if it still set it to 10.

>> Yeah.
>> I think it's set at 10 because it went through a function that called again.
>> I can see where you're going with that. But actually what happens is, that would only reset if we called outer function again, and created a whole new scope for the parent scope.

[00:16:37] But we're actually only calling this body of the function. So, it's only recreating this scope or it's like initializing a new execution context here, but it keeps the same one above it. The only way we can reset is by calling this and then it would reset this too.

[00:17:02] Oops, that makes sense? So with that, what do you think counter and outer scope is?
>> My goodness, it's still either [LAUGH] Is it?
>> Yeah, it's 12 and then it will be 13 when you add one.
>> Yeah, okay.
>> So actual now equals 13. And the interesting thing is, well, the thing to keep in mind is, okay, we're running this function in here.

[00:17:35] Where does it exit to? Ryan?
>> It should exit into the inner body of outer function, no?
>> It doesn't do that.
>> Then it would exit back to where it was called for.
>> Yeah, exactly, so some people assume since we're executing here, the next thing is that it would go run this again.

[00:18:01] But that's not the case, actually, so it's gonna run this and then it's gonna hop back, here where we called it and run the next line. And what do we think actual is? Any questions about this one?
>> But I thought since we weren't returning anything inside the retained inner function, like after during actual equals counter and outer scope, we weren't returning.

>> Yeah.
>> But you had mentioned something about that earlier.
>> Yeah.
>> Returning anything.
>> It's not returning anything. So when you call it here, this window. So, when you execute the function, it would return here. If we were saying like, our result equals that, then that's what we care about the return value.

[00:19:00] But what happen in the body of the function is that we assigned actual again to an updated value. And we're referencing actual, yeah. Yeah, that's a good question. Anyone else? That sounds a little bit of a mind bender. Do people feel like their minds being bent a little bit or they're like, I'm used to JavaScript by now and this is not news.

[00:19:29] So Vent-
>> Interesting that the function still has context for the outer scope, what do you call it?
>> Yeah.
>> Outside of the-
>> Yeah, looks like a little magic tunnel into another function.
>> So, you have a question?
>> You were gonna cover a let for the chat?

>> Yes, so the appropriate time to use let is when you want to scope your variable inside of a block, that's not a function. However, a lot of people just use let and const all the time, because it's ES6. And they believe that that's the right thing to do.

[00:20:16] I think as long as you know how your code runs, it's fine. Var does do some funny things with hoisting, which means that when you declare a variable somewhere, it gets hoisted to the top of its local scope as undefined. So for example, and this is why people don't like Var.

[00:20:41] So people who are like, like so if for example, console that logged this it would be undefined. It wouldn't throw an error. Typically if you're referencing a variable like if this wasn't here, it will throw an error. So we call this hoisting. And if something like that happens when your code is being like compiled and optimized in the back, it will hoist all of your variables to the top.

[00:21:21] It'll all be set to undefined and that's why it's recommended that if you're declaring variables in the body of a function, just put all of them at the top because that's what it's gonna do anyway. And it minimizes any changes anything happening that you wouldn't expect with the let keyword that is supposed to fix them.

[00:21:44] But, I pretty much still use Var work. For the most part, I'm trying to get past it and move on to embrace the ES6 stuff more but like I was saying before, pretty much at this point, I write all my stuff in ES5. And then I rewrite it in ES6, just because I'm just used to writing ES5, and I'm just forcing myself to do ES6.

[00:22:09] But it is really important to know and it's the new JavaScript and I have to just get used to it. You know what I mean? That's where I'm at at least. Take a look at all of the rules that we just went through for Scope. Can you guys read all this?

[00:22:30] So big enough? Okay, so let's take a five minute break and discuss with your little group, we're like in groups and 2s, 3s. What rule was most interesting or surprising to you in this exercise? Or what will you take away?