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

Kyle reviews the ES6 "let" keyword that will implicitly create a block-level scope and add declarations to that scope rather than the enclosing function. The most common use-case for the let keyword is for loops.

Get Unlimited Access Now

Transcript from the "Block Scoping" Lesson

[00:00:00]
>> Kyle Simpson: Lets talk about block scoping. IIFE is a good segway into if. We can use IIFEs as kind of a heavier weight way of creating a block of scope. There are some downsides to the IIFE. One of the things is they changed the meaning of the return keyword, for example.

[00:00:14] So if you were wanting to do a return inside of a for loop and you wrap an IFFE around it, now that return doesn't talk to the external function and now talks to the IFFE, right? So there are unfortunate side effects that we'll also remap, or what this keyword means, or what arguments means, and stuff like that.

[00:00:31] So it's kind of a heavier weight way of creating a block. Be nice if JavaScript had block scoping, unfortunately as of ES6, we now have the ability to create lightweight blocks. So I wanna give you some examples of why you're gonna use this or what's the appropriate way to think about block scoping.

[00:00:48] Imagine a function where I'm creating a variable declaration inside, in this case, an if statement. If I say var tmp = x or just the var tmp part, what I'm doing here is creating a temp variable that does belong to the scope of diff. Remember, we talked about the rules.

[00:01:06] It's gonna find that var tmp. It's gonna say hey, scope of diff, do you have a tmp that's gonna add it? There's gonna be one tmp variable for the entire function. And I theoretically could use that tmp variable on line 7 or 8 if I wanted to. But I've done something stylistically different here.

[00:01:22] Even though implementation wise, functionality wise, that tmp variable is available everywhere. What I've done stylistically is I've said to the reader of this code, the intent is for you to treat this variables only being accessible with inside of the if statement. There's an intent issue there. That's a stylistic decision.

[00:01:44] In the case where you were already wanting to stylistically signal something, but there's no enforcement. It's nice to know now that as of ES6, we have a let keyword that will enforce that which we were already stylistically signalling. The let keyword will literally create a temp variable that does not attach to the diff, the scope of diff, but rather to the scope of the if statement.

[00:02:10] As a matter of fact, the if statement didn't have a scope of before. The mere presence of the let keyword within the if makes the if also into a block of scope. And that way, it's sort of an implicit scope. It kind of hijack the if statement to create some scope and it insert to create an environment, and insert that temp variable into that environment.

[00:02:33] So now if we try to reference temp on line 7 or line 8, we get a what kind of error?
>> Kyle Simpson: A reference error because there is no temp in that scope. So this is a much lighter way of doing the IFFE thing that we just talked about.

[00:02:51] It allows us to create a block of scope in any place of our code simply by having a pair of curly braces there. That can become a scope by using the let keyword. I'm emphasizing that we are reinforcing a stylistic signal with a functionality enforcement because that is, in my opinion, the appropriate way to approach the let keyword.

[00:03:13] There are many people that have adopted or done what I've said over and over again that we developers are so good at which is take one little thing that's good and take it to its logical extreme. So, great, if the let keyword is helpful here, that means I should that everywhere.

[00:03:28] Get rid of that ugly var that I never liked anyway, and just use let everywhere. There are literally lots and lots of people, very prominent people, that have taken on that new, let is the new var sort of perspective. As a metapoint on the let is the new var end movement, or arrow is the new function movement, or back ticks is, template literals is the new string literal, or any of those things where we rush to say, let me take it to the extreme and say x is the new y.

[00:04:03]
>> Kyle Simpson: I will suggest to you that virtually never in the course of computing history nor ever in the future of computing history has there ever been a valid statement of x is the new y. Here, we invented this new thing, and at 100% with no exceptions, completely replaces the old thing, that just is not the reality of computing science.

[00:04:25] We create new stuff, yes. And we should use new stuff where it is appropriate. But it's virtually never the case that we completely eliminate some entire whole section of thing that we used to think was valid, and now it's entirely invalid. So when people say let is the new var, call bullshit on that because it is not true.

[00:04:43] Let is not the new var, it is let and var. Let and var will be useful in your code, and I'll expound upon that, okay? But don't rush to that cult wisdom of hey, I can just put my let in. People have literally suggested doing a global find and replace.

[00:05:00] I've seen T-shirts with the Ridge x global find and replace of let and var. Are you kidding me? Not only would that break a bunch of stuff, but it also just doesn't make any sense. We should be critically thinking about where is let gonna be useful? In my opinion, the usefulness of let is specifically to reinforce that what you are already stylistically signaling.

[00:05:24] Don't go looking for places to do block scoping in a place where that would be unnatural or weird. Don't just use the let because it's nice to always use let. Use the let where it's gonna be helpful, where it's going to enforce the thing you are already stylistically doing.

[00:05:42]
>> Kyle Simpson: By the way, I mentioned that the let inside of some block like an if statement, for example, is implicitly hijacking it and turning it into a scope. I actually think we should be more explicit. I think we should create explicit blocks of scope. Like I'm doing here, I just opened up a curly brace pair and I declared the variables at the very first top line that are gonna be block-scoped to that curly brace pair.

[00:06:05] There's a reason why I do that. First off, probably most importantly, I wanna be super clear and obvious at the beginning of the block, any variables that you might expect to exist only in that block. I don't wanna just sprinkle them throughout the entire block, because then it's a lot harder for people to figure out which thing is a scope and where did these things come from?

[00:06:26] Putting it at the top of the block makes it super obvious. We're gonna create a prefix and a REST variable. They're gonna exist only for this block. Secondly, the usage of the curly brace, that is not idiomatic to JavaScript by any means. We've never really done that before, but it's been syntactically valid since day one of JavaScript.

[00:06:44] It's just there was no reason to ever do that before. But this isn't something I've made up. If you've done block scoping in any other language in existence like Java, C++, etc., that's exactly how you do block scoping. You open up a curly brace pair and you make some variable declarations.

[00:07:00] So all I'm saying is, why don't we use that 50 years of precedent, and just just keep doing that in JavaScript? You know what's not precedented? Accidentally high jacking existing blocks. That's not something that's very idiomatic in those languages. People create explicit blocks, cuz it's easier to read and understand.

[00:07:18] So all I'm saying is we ought to do that. And that means instead of just putting a let inside of an if, why don't you go ahead and make a curly blazed pair inside of the if to make it super obvious, there is a scope being created here?

[00:07:30] I know we're allergic to nesting and white space, indentation. Those things are free, and they help with readability. You should use them to that extent. So I prefer and recommend that you consider creating explicit blocks of scope. And, by the way, you're gonna get some practice on this in just a moment, cuz we're about to have an exercise that lets you practice, where should I use a var or where should I use a let?