The let keyword adds block scoping to ES6. While some developers believe the let keyword should replace the var keyword, Kyle disagrees. He spends a few minutes comparing the two keywords and sharing examples of when one should be used over the other.
(oriental music) - What we want to do now is turn our attention to things that I really do think we should be using more. These are more the right parts of ES6. The first thing I want to talk about is block scoping. So quickly I'll motivate block scoping. I've covered these sorts of things in many of my other classes as well. So I don't want to keep repeating. But just want to quickly motivate. Let's say I have a function called foo, and there's some condition by which I want to swap those two like for example, the case where x is greater than y.
Normally you do something like this. Then you say, y equals tmp. We've used the var keyword inside of an if statement. Now, functionally meaning operationally, the var keyword here is attaching a tmp variable to the scope of foo. That's what people like to call hoisting. Hoisting is made up, it's not a real thing but that's the metaphor that we use to describe how lexical variables are attached to their lexical environments at compile time, okay.
So it's hoisted to the scope of foo. But why do we put it inside of the if statement. What is going on stylistically? 'Cause this is the thing that people do. They'll put their var keywords in specific locations even though they know they've actually behave as if they belong to the whole function. Well, what we're doing here is we're stylistically saying I want the tmp variable to belong only to that if statement. That's what it's for. Another example is when you have a piece of code like this, and you do a for var i equals.
Then you have some code inside of the for loop. The var i here is gonna be hoisted to the scope of foo. The i is available everywhere, but why do we put it on the for loop? The reason why, at least for most of us, the reason why we put it on the for loop because we are stylistically signaling to the reader of this code, i belongs to the for loop. Don't use it before or after. Even though you can, don't. Even though you can use tmp elsewhere, don't. It's supposed to be used only for this if statement. These are the kinds of scenarios under which block scoping makes entirely sense.
Meaning I want tmp to belong to the if statement. Now tmp actually does belong to the if statement. If we try to use tmp before or after it, we're gonna get an error. If we try to use i outside of the for loop, we're gonna get an error because the let keyword is going to enforce that which we were already stylistically signaling. That is how I think you ought to approach this let keyword, to enforce the things that you already stylistically signaled. Does that mean that you ought to make all of your vars into lets, as some people are liking to say right? Let is the new var.
They're missing the fact that the var keyword actually tells us important stuff. The var keyword tells us when used in those positions, this is a variable that I intend to use across the whole function. The let keyword doesn't tell us that. It's position tells us that but the let keyword itself does not visually signal what our intent is. If you use the var keyword here, it is now telling the reader of this code, I know what I'm doing, and I'm intending to use z everywhere. So my personal take is you ought to use both let and var.
Use vars in the places where you intend to use them across lots of scopes. Use lets in the places where you were already stylistically saying, I want to contain it to this block. I think that's what it's good for. So I don't believe in the let is new var. I believe let and var. Let is the new helper to var. It helps you enforce the places where you wanted var to be block scoped all along. Yes? - [Attendee] Question from the room. - Sure. - [Attendee] I've heard, quote, only use let in places where you want the value to be mutable, cons everywhere else.
- We're gonna talk about cons in a little bit. I'm not there yet so we'll come back to that question. Okay, I'm just talking about how you decide and again just like with the error function, I'm trying to present to you the different cases here 'cause I want you to creatively think. As engineers, I want you to analyze. Don't just follow some written rule. Think about which one is more appropriate? Which one communicates better? Okay, so some other places where I think the var keyword is actually superior to the let keyword.
That's one of the big sins in all of programming. Whenever one fix causes another problem. What's my another problem? My another problem is now z doesn't belong anywhere else. So even if I figure out what's wrong here, I'm gonna get another error that says z is not defined. I'm like, what the hell? Z is clearly there. Oh crap, I forgot I had a let keyword. So whenever I'm doing that, create little like debugging, I'm gonna have to remember in those places, oops, this thing can't just be try caught, I need a var there.
Or you're gonna do what some people say which is, oh no, no, no, what you should have done is you never should have had those two together. You should have had the let z separate. Then the z equals bar in its own separate thing. So you should have those separate. There's your problem solved, right. This is the argument that's often made. There's your problem solved. Now, what I'm gonna say is this. I think, this is personal taste. I think that one of the things that aids readability in my code is when the declaration, the first usage of a variable is as close as possible to the declaration of that variable.
By as close as possible, I prefer them to be on the same line. But if they can't be on the same line, I really want them to be as close as possible, okay. In this particular example, they're only separated by two or three lines, no big deal. But as things go, as our code evolves, you might start to see more separation between those. Could be five lines, could be 100 lines, could be 1,000 lines between the place where it was declared, and the place where it was used. As soon as you start to create more and more visual separation especially more than about three to five lines, now you have a visual readability problem because somebody's gonna look at that line z equals bar, say wait a minute, where does z come from? They're gonna have to go hunting for that let z.
They have to make sure that they didn't cross any curly brace boundaries that they really found at exactly the same scope as the place that it was. So I think you ought to use your variable declaration as close as possible to where you're gonna use them the first time. That also means that if a variable is used in two very different places in the code, I'm gonna shock you and say, I think you ought to declare it twice. You ought to declare it up here where you use it, and then you ought to re-declare 1,000 lines later when you use it way down here.
You can't do that with the let keyword. You can't re-declare with the let keyword 'cause you're gonna get an error. This is one of those places where in my opinion the var keyword shines 'cause it allows me readability-wise to put that little notation down there at the bottom, hey, I'm just reminding you that z is coming from this outer scope. So I put the var z down there at the bottom. Another place where that shows up is in if statements. I regularly do this in like. I'll have some kind of condition, doesn't matter what the condition is, and I'll have a whole bunch of variables that I create and initialize based upon these conditions.
So I'll say var w equals, and var r equals over and over, and over again. Then I'll have an else, some other condition. I'll have a different set of initializations for those. Maybe a whole different set of logic that's happening in that particular case. Then I'll do another else, and I'll re-declare them again, and again, and again. Do you spot the problem if I use lets here? I'll be block scoping those if statements.
These are not really if blocks in that sense. They're not really block. They're not really scopes in that sense. They're just collections of assignments that I want to conditionally happen. Don't go using some crazy set of turn eerie stuff to do this. Just use the var keyword. If you want, go ahead and be super redundant, and put the var keyword declaration also outside of the if statement. Because what you're trying to do really is not to write as few characters as possible. To write as many characters as it takes to get your message across 'cause you want to communicate better.
At least, I hope that's what you want. That's what I'm trying to get at here, okay. So I think there are places operationally and stylistically that the var keyword and the let keyword can be used together. They have different purposes and one does not replace the other. We ought use them together.
This course was created by Frontend Masters. It was originally released on 01/10/2017. We're pleased to host this training in our library.
- The arrow function
- Arrow function variations
- Closures and explicit blocks
- Default values
- Using the gather and spread operators
- Dumping variables
- Concise properties and methods
- Symbols, iterators, and generators
- Optimizing codes for the reader