Deep JavaScript Foundations, v3

Function Scoping

Kyle Simpson

Kyle Simpson

You Don't Know JS
Deep JavaScript Foundations, v3

Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "Function Scoping" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle presents arguments in support of the core principle of strategically hiding information in levels of scope.


Transcript from the "Function Scoping" Lesson

>> Kyle Simpson: So what can we do with this knowledge of scopes? And, specifically, we've been focusing on scopes that are organized by functions. What can we do with that? What sorts of abilities or problems does it help us solve? It's not just theoretical. We are doing this because we're trying to build towards a pattern that helps us organize our code better.

So to build towards that pattern, let's start doing things with our functions. Let's talk about this example, obviously very simple and silly. But we have a variable, and then later in the program we are using the variable. And we're hoping that it still has the same value. Right now, everything looks good.

But six months from now, a junior developer, not knowing what they're doing, not because they're dumb but just simply because they didn't see it, not knowing, comes along and inserts this code in between.
>> Kyle Simpson: You can immediately spot the problem, there's a name collision. They chose to name their variable the same as the variable that already existed in that scope.

And when they overwrote it on line 6, it ended up breaking line 10 in a non-obvious way.
>> Kyle Simpson: Now, you might be thinking to yourself, well, that's why I should have used a const. Except that wouldn't really have fixed this. It would've thrown an error to a junior developer, who then probably would have just changed your const to a var anyway.

That doesn't really fix this problem. The real problem, the real root problem, is not that the variable could be reassigned, but that we have a naming collision problem.
>> Kyle Simpson: We have a problem where two different entities wanna use the same semantic name for some purpose.
>> Speaker 1: In the same scope.

>> Kyle Simpson: In the same scope. So how do we resolve this problem where we can't have two different usages of the same name in the same scope without them conflicting, without them colliding, but how do we fix that? Well, naturally, we could put them in different buckets. And the best way that we've seen thus far Is to wrap a function around it.

So if I make anotherTeacher function here and I declare line 4 that variable, now it's a different colored marble, right? It's a blue marble, not a red marble. So that variable doesn't end up conflicting with the one in line 10, everything still works. The problem is that now I have a function that has a name in that scope.

It has the name anotherTeacher. So I didn't really fix the naming collision problem at all, did I? I just shifted it to a different variable name.
>> Kyle Simpson: It is true that we now have a new scope, and we can contain any assignments of that scope, but we still have a naming collision problem.

>> Kyle Simpson: There's a principle within software development, it's called the principle of least exposure or the principle of least privilege, depending on which Wikipedia page or which CS textbook you had. Either way, whatever it's called, the principle of least exposure or privilege says this. You should default to keeping everything private, and only exposing the minimal necessary.

>> Kyle Simpson: That's one of the core principles of software engineering, because it essentially sets up a defensive posture. It's a defensive approach that says, I don't wanna make my stuff available because I don't want these sorts of problems. As a matter of fact, there are three main problems that we solve by this defensive approach of the least exposure or least prevalent principle.

Number one, we have naming collision problems. And if you hide something within a scope, or hide something on a namespace or do some other sort of hiding, then you reduce the surface area for name collisions. So number one, we have name collisions. Number two, if you hide something, it means that somebody else can't accidentally of intentionally misuse that thing.

If you expose it publicly, everybody can use it. And they definitely will use it, even if you tell them not to. If it's exposed, you can guarantee that, at some point, somebody's gonna use it. So if you hide it, then you prevent them from accessing it. But the third one, and probably the most core and important reason for this principle, it's often overlooked.

If you hide something, like one of those implementation details, or like a variable name, you protect yourself for future refactoring. If you expose something, it's a guarantee almost, there's gotta be some CS law for this, it's a guarantee that somebody's gonna use it. And as soon as they start using it, now you are restricted in your ability to freely refactor it.

Because if you refactor, you break their code. And if they have an important enough job title in the organization, they're gonna squash that, right?
>> Kyle Simpson: It's almost like I've seen that happen a few dozen times [LAUGH] in my programming career, okay? So one of the most important reasons for hiding things is to prevent there being that sort of overlap, and give you the space to say, you know what?

I don't want to call it that at all, and I don't want it to be an array at all. I wanna refactor it to be a different way. This principle is playing out in what we're seeing in our code. In this particular case, it's the name collision, but it could have been either of the other two reasons as well.

We see it playing out and we need to solve it, and the way we need to solve it is it with our understanding of scope. But, right now, this usage of a function is not really accomplishing that task, so we need a better way of using our knowledge of scope.

We need to create a scope, like with a function, but we need to somehow not pollute the enclosing scope with some name, so that we don't have this naming collision issue. To figure out how to do that, I'm gonna take you through a small little derivation. I want you to go back to our earlier discussion about how the line 8 would execute, and I want you to think about it in those two steps.

Remember, the first step was to figure out what's in the marble, and then the second step was the parentheses to execute it. So I want you to think about those as two steps, and I'm gonna make it super obvious by wrapping a parentheses around the first step. By the way, that code still works.

It looks weird, but it still totally works. You can put parentheses around a function and it's still gonna execute. And the reason it's gonna execute is cuz it's gonna do the same thing as in the previous slide, essentially, which is to go get the value in that variable first, and then the second set of parentheses is gonna execute it.

Learn Straight from the Experts Who Shape the Modern Web

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