This course has been updated! We now recommend you take the Deep JavaScript Foundations, v3 course.
Transcript from the "Lexical Scope" Lesson
[00:00:00]
>> Kyle Simpson: So I referred to this lexical scope several times. And that is the model by which scopes are nested within each other that we described earlier in this course. This process of putting a function in scope and perhaps inside of another one. And referencing variables and accessing them outside of the scope, that is the lexical scope model.
[00:00:19] I find it strange sometimes that people suggest that JavaScript does not have lexical scope, where they will claim that something like Java or C++ has lexical scope. Because from the perspective of a compiler author, they absolutely have the same scope model. There are some nuances that we'll talk about, mainly what we refer to as hoisting.
[00:00:39] There are some nuances that are slightly different in terms of your expectation. But even those are not particularly onerous to get your head around. It's just that most people never actually learn it. So, it's just like when we talked about coercion earlier in the course and said, you know, most people said it's just too hard to learn coercion.
[00:00:55] So I don't even wanna learn it, so it must be poorly designed. If you learn these rules it's actually pretty straightforward. So I would stand firmly on the fact that JavaScript absolutely has lexical scope. There is another model for scoping. I hinted at this earlier, it's the dynamic scope model.
[00:01:11] And I wanted to quickly compare those two. So lexical scope, you'll notice that I have a bar variable. And when I reference that bar variable on line 5, the compiler has said, I know which bucket you come from, it's from this one. So that reference again, it's permanent, it's fixed.
[00:01:29] It's not gonna be like some dispatch where we figure this out at runtime. There's a fixed relationship there and it's never gonna change. No matter what you do with that baz function, even if you pass it to other places, it's always gonna refer to that exact same function.
[00:01:42] No matter how you call baz, where it's called from, it'll always refer to that exact same bar variable from line 2. That's a good nice predictability to lexical scope. And I would say that's one of the biggest benefits of lexical scope. As a matter of fact, the predictability leads into more optimization.
[00:01:59] Virtually all programming languages have lexical scope. And I think one of the reasons for that is that lexical scope is more optimizable. Because we don't need to decide at runtime where these variables come from. We can figure that out once at compile time and reuse that information. If every time we call baz, and every place that we call baz from we might get different answers which bar variable it referred to, that would be very much more dynamic and much harder to optimize.
[00:02:25] Do we understand that part? So that's lexical scope, by contrast, if JavaScript had dynamic scope. Sorry I wanted to point out that of the ways that I like to visualize this is nested bubbles of scope. For me that's a little bit even more helpful than the building metaphor, I like these nested bubbles.
[00:02:43] They're strictly nested, it's not like Venn diagrams, they don't cross lines. Because it would make no sense for the baz scope to be partially in two different parent scopes. So they're entirely nested within each other. I wish there was an editor plugin that could draw these lines around my scopes or whatever.
[00:02:59] By the way, another shout out to Doug Crawford. He had buried as a little tidbit in one of his talks that I watching at one point and this is from years ago. He talked about Syntax highlighting in editors and he talked about Syntax highlighting as being a silly thing that only uninformed developers need which was a really bizarre statement to make.
[00:03:22] But then he made the case, which actually the reason I'm bringing this up, he made the case that what we really should have is not syntax highlighting but scope highlighting. And he showed an example where he had code where they were nested scopes, and the variables were colored according to what scope they belonged to, and I thought that was genius.
[00:03:37] I wish we had that, I wish that tool existed, cuz I'd be using that with my slides for sure.
>> Kyle Simpson: [COUGH] So, here is dynamics scope. As by comparison here we have a full function that references a bar because it doesn't have its own bar, we have to figure out where is that bar gonna come from.
[00:03:53] And we would normally think, well it's gonna go to the outer scope, in this case the global scope. But in a dynamically scoped language, it would not matter where the function was written or where. Or in any way perform how it was called. It will only matter where it was called from.
[00:04:09] So here we wrote it on line two but we call it from line eight. And that's would be how it would decide.I'm gonna go back to where you were called from. I'm gonna walk up the call stack and console each of the scope call stack to figure out.
[00:04:23] Which variable to use. It would still be a first come first serve dispatch to find that variable. So you notice now that we have the same foo function. If it was called from a thousand different locations, we'd get a thousand different answers as to what the bar variable points at.
[00:04:39]
>> Kyle Simpson: The tradeoff here, of course, Is that now things are not predictable, but they are much more flexible. We've now got a system where a function could be written and be used in many different contexts. Now this is hypothetical, this isn't actually how JavaScript works. So don't worry that all of a sudden, your whole world is coming down like no, what am I doing, right?
[00:05:00] This is theoretical. But, if JavaScript had a mechanism kind of like this, where we could write a function in such a way. And then make it dynamic in terms of how it resolves reference to variables. We could do that, could we all agree that that would be a nice, interesting, additional use case for JavaScript.
[00:05:19] That we would have not only lexical scope, which is predictable, but we'd also have this mechanism that was dynamic and more flexible. And having both of those in the language is a powerful thing. Most languages only have one or the other. And having both of them in the same language is one of the things that I think is most unique and interesting about JavaScript.
[00:05:40] So while this is not actually how dynamic scale works, we will see the "this" keyword later in our course. And that will give us a clue to how we can do something like dynamic contexting. Just keep those two ideas, the fixed lexical author timescoping decision that's predictable compared to this dynamic scoping thing that's dynamic and more flexible.