This course has been updated! We now recommend you take the Deep JavaScript Foundations, v3 course.
Transcript from the "Execution of Function Code" Lesson
[00:00:00]
>> [MUSIC]
[00:00:04]
>> Kyle Simpson: Now, we don't see the executions of the declarations of function bar and function baz anymore. As a matter of fact, from an executional perspective, lines 3 through 10 don't exist anymore, because they've been declared elsewhere. But let's pretend bar is going to be called, so let's execute the function bar.
[00:00:22] We're inside of the scope of bar now and we need to execute line 4. Remember, the var doesn't exist anymore. So how are we going to to execute line 4? Everybody tell me, what questions needs to be asked and what is that gonna it sound like?
>> Male Speaker 1: Ask the scope for function bar manager, what foo is.
[00:00:45]
>> Kyle Simpson: Hey scope of bar, I have a what kind of reference?
>> Male Speaker 1: Variables.
>> Kyle Simpson: Is it an LHS or is it an RHS?
>> Male Speaker 1: LHS.
>> Kyle Simpson: I have a LHS reference for variable called.
>> Male Speaker 1: Foo.
>> Kyle Simpson: Foo, never heard of him. What's the answer gonna be back from the scope of bar?
[00:01:03] Yep, you declared him just a little while ago when we compiled the function, here ya go. This is gonna hand us back a reference, now we go to the right hand side again. The right hand side's an immediate value, I wanted to make this code a little simpler.
[00:01:12] So we got an immediate value, we can just copy it, and execute that operation, that assignment operation from line 4. Everybody with me so far? Okay, feel free to ask questions, feel free to stop. This an interactive class. You don't wanna just hear me drone on all day.
[00:01:26] I want you to be able to interact with this.
>> Male Speaker 2: Can you ask the local scope or something?
>> Kyle Simpson: Say that again.
>> Male Speaker 2: The foo, we did not research the local scope or something. We did not say hey, I have local scope for foo.
>> Kyle Simpson: That's exactly what just happened.
[00:01:40] It might've been subtle, but our conversation said, hey, scope of bar. So we're asking the local scope of bar, do you have a variable called foo? We always ask our local scope first before we go elsewhere. And we'll get to that in just a minute, okay? All right, so now let's execute the function baz.
[00:01:56] And again, for the purposes of our discussion, we don't see the baz being executed. So let's ignore any assignment that might've happened to the foo ahead of time. Let's just execute baz as it stands. How are we going to execute line 8?
>> Male Speaker 3: Hey scope of baz, do you have an identifier named foo?
[00:02:17]
>> Kyle Simpson: What kind of a reference do I have for it?
>> Male Speaker 3: Left handed.
>> Kyle Simpson: I've got a LHS reference, again I keep hammering on that. That sounds like an irrelevant point, but we're gonna see why it's actually really relevant. I have an LHS reference for a variable called.
[00:02:29]
>> Male Speaker 3: Foo.
>> Kyle Simpson: Ever heard of him? What's the answer gonna be?
>> Male Speaker 3: It's in my definition.
>> Kyle Simpson: It's in my definition because I had a parameter named that. So I have a local variable called foo that I can reference. So it hands us back a reference to that so we can assign a value to it, everybody with me?
[00:02:42] We then assign bam into that foo. Now when we assign to that foo, are we assigning to that guy or to that guy? No, obviously not, because the guy that we got returned, we asked our local scope first, and that's the guy we got returned. Here's where things get interesting, and here's where people start to get pissed off at JavaScript.
[00:02:58] Let's execute line 9. How is line 9 gonna to execute?
>> Male Speaker 1: Badly.
>> Kyle Simpson: Yeah, badly, good answer.
>> Male Speaker 4: It'll ask baz.
>> Kyle Simpson: Hey scope of baz, I have an-
>> Male Speaker 4: Bam.
>> Kyle Simpson: I have an LHS reference for a variable called?
>> Male Speaker 4: Bam.
>> Kyle Simpson: Ever heard of him? What's the answer gonna be?
[00:03:16]
>> Male Speaker 2: Nope.
>> Kyle Simpson: Anybody ever played the, what was that?
>> Male Speaker 5: Are we in strict mode?
>> Kyle Simpson: We are not in strict mode. We see no strict mode. So the answer's gonna be, never heard of it. Anybody ever heard of the card game Go Fish? Sometimes I give this class in cultures where they don't know that card game, so it misses this reference.
[00:03:34] The card game Go Fish, where I've got some eights in my hand and you ask for eights and I have to give them to you. But if you ask for nines what do I say if I don't have nines in my hand? I say, go fish. So it's kind of like that.
[00:03:44] We ask the function baz, hey scope of baz, ever heard of a variable called bam, cuz I got an LHS reference for him? And the answer is, go fish. I don't got it, never heard of it, go fish. So where do we go? Well, we go out one level of scope.
[00:03:57] So we begin to think about these scopes as being nested inside of each other. And we'll get to nested scopes in a little bit, more formally. But what we see here is, because I cannot fulfill that reference for bam inside of my local scope, the next place that I go is to my global scope in this case.
[00:04:11] It could've been a surrounding function, could've been 15 levels deep, it doesn't matter. But I would go to the next outer, and then the next outer, and the next outer. Course, once I get to the global, it's either gonna find it or not, but I have nowhere else to go beyond the global.
[00:04:23] But we're at the global so we're gonna then say, hey global scope, I've got an LHS reference for variable called bam, ever heard of him? And what's the answer from the global scope gonna be?
>> Male Speaker 3: Just did.
>> Kyle Simpson: [LAUGH] The answer's gonna be, yes I just created him for you.
[00:04:38] And that's where people get really pissed off. Because we're not in strict mode and we would expect for the global scope to say, no never heard of him. But unfortunately, it will go ahead and create one for us because we had a LHS reference, and here's why that's important.
[00:04:52] If it had been an RHS reference, it would've been different. But because we have an LHS reference and we get to the global scope and we're in non strict mode, he's gonna say, I tried to be a helpful guy. I went in and created a bam for you in the global scope, not in your local scope, but in the global scope.
[00:05:07] Then so here you go, and you hand it back. So when we make this assignment, are we assigning to a local variable or to a global variable?
>> Male Speaker 3: Global.
>> Kyle Simpson: The global variable, the bam. And that's where we get this idea of leakage of global variables. That's how it happened.
[00:05:21] Because we didn't find it in our local scope, we stepped out to the outer scope, and because we're in non-strict mode, he responded back and he said, I went ahead and created one. Now had we been in strict mode, which I recommend you write your code in from now on, by the way, had we been in strict mode, the answer would've been nope, never heard of him.
[00:05:38] Now, if you get to the global scope and you get back an answer that says, nope, never heard of him, that's an error condition. Because you're trying to assign to somebody that's not been declared. This is an important key difference and we're gonna come back to this a couple times today throughout the rest of morning and this afternoon.
[00:05:52] The difference between something being declared or not. If it was declared, there's gonna be a var somewhere or a function somewhere, that's required to make something declared. If you do not see a declaration somewhere, it is in the state that we would call undeclared. Which means, basically, that we were unable to fulfill a request to find that reference in any of the scopes that we had access to.
[00:06:15] So an undeclared variable means we were unable to find an LHS, a proper LHS reference for it in any of the scopes that we have access to. Does everybody follow that? Okay, now there's another word in JavaScript which is undefined. And I'm sure all of you have heard undefined.
[00:06:33] A lot of people think that the word undeclared and the word undefined are synonyms of each other. That undefined means the same thing, and that's totally false. The word undefined and the word undeclared are very, very different from each other. Undeclared is what is should have been called when there's no present declaration for the variable in any of the scopes that we have access to.
[00:06:53] Undefined means he was declared, but he has this special empty value that we mistakenly called undefined. Shouldn't have been called undefined, it should have been called something else entirely. But it really is more akin to the word uninitialized. The undefined is a proper value, it's not the absence of a value, it is an actual value.
[00:07:16] It's kind of like in physics and in space, like a vacuum, there cannot be a vacuum where there's no value. So whenever you remove everything else, the undefined value immediately injects himself. He's a proper value, he exists, but that does not mean undeclared. So keep undefined and undeclared distinct in your minds.
[00:07:36] Any questions so far? I told you, I promised we'd spend 20 or 30 minutes on this one slide. Any questions so far about this idea of asking our scope engine about LHS references? Okay.
>> Male Speaker 2: When you say-
>> Kyle Simpson: Go ahead, then I'll get to you.
>> Male Speaker 2: When you say undefined, is there any actual value, or what exactly is told by the compiler?
[00:07:58]
>> Kyle Simpson: There is actually a proper value called undefined. If you look it up in the spec, undefined is an actual value, it's a type that exists that has one value in it. There is an undefined. Get to you in just one sec, Will, cuz I have this question over here.
[00:08:11]
>> Male Speaker 6: I'm just wondering if you could speak to some of the nuances in IE8 for the scoping, if there's anything.
>> Kyle Simpson: Nuances in IE8. Well, you might have to be a little bit more specific.
>> Male Speaker 6: I know, I've never really fully understood it, but I know that window doesn't always equal global in IE8, and I was just wondering if you had any?
[00:08:38]
>> Kyle Simpson: So, I don't really have a good example that I could explain of a condition where window would not be global. If you could come up with a concrete example I could kind of look at.
>> Male Speaker 6: They've changed all of their script floaters, and now they explicitly declare window.gac or .iba.
[00:09:00]
>> Kyle Simpson: Who is this?
>> Male Speaker 6: Google, or analytics. So originally they just told you to use gac, var gac, but I guess there is some problem with IE8, that multiple scripts don't use the same scope. So if you declare a var in one script and then you declare it later it will actually override, it does something weird.
[00:09:21] The window where globals go, and that's just kind of what, I guess my question.
>> Kyle Simpson: We are going to have to dig into that over a lunch break-
>> Male Speaker 6: Yeah that would be perfect, okay.
>> Kyle Simpson: I'm not familiar with that particular scenario.
>> Male Speaker 1: Awesome.
>> Kyle Simpson: That sounds like an awful bug, if that's true.
[00:09:35] Yeah, Will?
>> Will: Mine wasn't a question so much as just a comment, if everyone could speak up for their questions, sometimes you can't hear it on the stream.
>> Kyle Simpson: I'll try to repeat the questions.
>> Will: If you could repeat the questions that sound quiet, that would be great.
[00:09:46]
>> Kyle Simpson: Perfect, thanks, yeah.
>> Male Speaker 7: My question is, if you had declared foo in the function baz.
>> Kyle Simpson: Uh-huh, you mean I'd have a var foo here?
>> Male Speaker 7: Yep.
>> Kyle Simpson: Uh-huh.
>> Male Speaker 7: The argument that's passed in would be the var foo that was declared on line 1, or?
>> Kyle Simpson: So the question is, if I had on line 8 if it had also said var foo.
[00:10:09] So I've got a variable declaration for foo as a parameter name, and then I try to essentially sort of redeclare it, is what a lot of people would think that was doing. What would happen? Is that your question?
>> Male Speaker 7: Right.
>> Kyle Simpson: Okay, so the first question to answer, we're gonna go back to the compiler phase.
[00:10:24] We haven't dealt with multiple declarations, but the first thing that would happen when we were compiling function baz, is that we would declare the variable foo by virtue of the named parameter foo. So we would declare the foo. The next time we run across a var foo anywhere in that function, it's gonna say, hey scope of foo, I have a declaration for foo.
[00:10:45] And the scope is gonna respond back, no big deal, I've already gotten it. Because I've already declared it. Now, that's for variable declarations. There will be a subtle nuance that function declarations are able to override each other. But for variable declarations, it just essentially would've ignored that that subsequent var, had we put it there on line 8.
[00:11:05] That answer your question?
>> Male Speaker 7: Yeah so then within that function, foo would be, would override var with bam.
>> Kyle Simpson: On line seven and a half, foo might have a value that was passed into him. For our purposes we're ignoring whatever value was passed into him, we're overriding it.
[00:11:23] So it is the same variable.
>> Male Speaker 7: All right.
>> Kyle Simpson: We're overriding it. But we could have, on line seven and a half, could have console logged out the initial value. And if we passed it in as the number 42, it would have that value before it gets to line 8.