This course has been updated! We now recommend you take the Deep JavaScript Foundations, v3 course.

Check out a free preview of the full Advanced JavaScript course:
The "Problems with let keyword" Lesson is part of the full, Advanced JavaScript course featured in this preview video. Here's what you'd learn in this lesson:

Kyle describes a few issues he has with the let keyword. Some of his issues are stylistic, but others are related to common variable functionality like hoisting. Kyle discusses his solutions for these issues and a tool he created to help.

Get Unlimited Access Now

Transcript from the "Problems with let keyword" Lesson

[00:00:00]
>> [MUSIC]

[00:00:04]
>> Kyle Simpson: But there's some problems with the way this particular formulation of the let key word exists. Some problems at least in my opinion. The first problem is the let key word, we're going to talk about hoisting in just a moment, the let keyword does not hoist. Which means that right here I'm showing the let keyword at the top of this if statement.

[00:00:24] What if this if statement was a thousand lines long, and I stuck the let keyword right in the middle of those thousand lines? You would be of the habit of thinking that baz variable would exist for the entire if statement. It turns out it would not exist until halfway through the if statement.

[00:00:40] So that's a gotcha that you're gonna have to worry about. You're gonna have to remember essentially to manually put all your lets at the top of your blocks. That's kind of a problem. The other problem is it creates an extra mental tax for refactoring, I know most of us in this room, and most of you online, you already write perfect code and you don't have to refractor.

[00:00:57] But for me, I usually will write a piece of code and it doesn't work, so I wrap an if statement around that, a four loop around that, and a tricatch loop around that. And eventually after putting enough blocks and moving things around, I accidentally stumble upon correctly working code.

[00:01:11] That's my process, I don't know about you. But for me, when I'm using variable declarations I don't have to worry about putting blocks everywhere. Now that I'm gonna use blocks scoping, I'm gonna have to think a lot more about my blocks, because I can't just arbitrarily wrap a new block somewhere, or put something somewhere, because I might, accidentally, create some block scoping that I wasn't thinking about.

[00:01:30] So, there's some extra mental tax to worry about when block scoping is introduced. Okay? So that's part of the problem. And the third thing I would say is, kind of leads from that second one. When you're talking about implicit block scoping, which is what the let keyword here is, it's implicitly sort of hijacking the scope of whatever block it exists in.

[00:01:50] When you talk about implicit, that's usually harder to maintain than explicit mechanisms. So I prefer to have explicit scope blocks, rather than implicit ones. Because if I'm going to deal with the mental tax, it would be nice if there was a way for me to know this is clearly a block of scope, rather than this is both an if statement, and potentially a partial block of scope or something like that.

[00:02:13] So, for me I prefer this other form. Which in the previous slide we would say would be a declaration, these are called let blocks or let statements. Kind of a similar syntax except we create an explicit block, like we see here on lines two through four, creating an explicit block for that binding to exist in and that variable exists only in that block, and not outside of it.

[00:02:35] Now rather than overloading my if block with additional scoping, I have an explicit block, that I can reason about that block as an independent unit just like I reason about functions. So I prefer this form to the precious form because I think it forces my, first of all, syntactically it forces my declarations to the top of the block which means they will always exist for the whole block.

[00:02:57] I don't have to worry about that, and it creates these explicit blocks, so it's a reduction of the mental tax by a little bit. Now that's just my own personal opinion, unfortunately there's a major problem here. And that is that the TC 39 committee decided to reject that syntax from ES 6.

[00:03:14] They make them later. But as a VS six, they decided to take the form which I think is the lesser, inferior form. And they kept that, and they rejected this. And I actually cried for a few days, cuz I really felt bad about this. I'm out in the habit of trying to tell people I think this is gonna make code better, and they rejected it.

[00:03:31] So the first question I asked myself, is there a way to solve this? Is there some kind of solution in terms of a syntactic form that might appear, and I came up with this idea. I said, what if I create an explicit block with just two curly braces.

[00:03:44] That's not very idiomatic in java script. Most people don't even know that you can do that but you can. You just put any two curly braces somewhere, and put my let declarations. Force them to be one statement all at the very top of my block. And even put a little comment there.

[00:03:58] And it looks a lot like a let block. It doesn't behave exactly like one, but it looks a lot like a let block, and so maybe that'll solve my problem. And that was my initial solution to this, of them not putting in the let syntax. But then I got to thinking, you know, whenever we have problems where languages are getting in our way and they're making things harder for us, the solution to that is not Write worse code the solution is make a better tool.

[00:04:24] So I thought, what if it would be possible to make a tool that would take code that looked like that, and make that code run inside of standard JavaScript browsers even though it's not standard JavaScript. Is that possible? Many of you are aware of tools like CoffeeScript. It transpiles something that's not standard JavaScript into something that is, and therefore, now it'll run.

[00:04:45] So, could we create a transpiler that would do this, and I did that. I made a tool, it's called let-er, and it's not just a theoretical thing, it's a real tool. I use it in my own code, it's got tests and everything. But what it does is it looks through your entire code base, and you'd use in your build process just like you use any other build tool.

[00:05:04] It transpiles any let blocks into something else that will work in JavaScript, in standard JavaScript, but it leaves everything else alone. So it's not like CoffeeScript, where it's rewriting all of your code. It's only going and looking very targeted at your let blocks. This allows you to start writing let blocks right now and use them, even though they're not standard.

[00:05:23] So it's a non-standard transpiler for you. But there's another benefit because guess how I actually accomplish the block scoping. It will take code like that, and it will trans file it to this code. Now, this code looks awful and ugly. What I'm actually doing is forcing a tri catch condition, by throwing something and forcing a catch block.

[00:05:45] Remember how I told you the mental bookmark that catch blocks are block scoped? So we can wrap a tri catch block around something and force this variable foo to be block scope. That will actually be enforced by the engine. And not only that, but now that works today in all browsers instead of waiting only for ES6 browsers.

[00:06:05] So you have a choice. You can wait around for ES6 or you could start using block scoping today. By virtue of a tool like letter. Now, nobody would write code like that. It's terribly ugly, but you also wouldn't write the code that comes out of the coffee script compiler.

[00:06:18] That's also equally ugly. The point is that this is compiled or generated code as opposed to authored code. You write code that lets you maintain your code nicer with wet blocks, and then you compile it to stuff that runs. Final note that I'll make on this. A lot of you may think it's ugly, and it's certainly non-performant, and it's terrible, and some crazy hack that Kyle came up with it.

[00:06:43] The official TC39 tool, it's called tracer, it's maintained by the team at Google, it's called Tracer, it is an es6 to es5 transpiler. And the committee uses this tool to test all of the things that they're specifying for es6 to be able to test them in existing JavaScript engines, and it transpiles things to work in es5.

[00:07:04] Guess what the tracer compiler does when it comes across a let keyword, produces a tri-cutch. So this is actually the official, blessed standardized way that you can use let block, block scoping with a let key word today, is to use something like tracer or to use something like this let-er.

[00:07:24] The vantage of the let-er tool is that let-er lets you use the more I think the more robust form of the let log form. But, in either words, that's a path forward for using box scoping today. By the way, that's a general pattern for what the TC 39 committee has suggested.

[00:07:43] Some people of the opinion that we're just gonna have to wait around for a decade until all browsers are ES6 compatible, and that sucks. That's not the way to do it. So their suggestion is that you start using ES6 today. Even though they're still working on it. There's a lot that is already finished.

[00:08:00] And they suggest that you use ES6 today and you start using a transpiler in your build process. So you'd put tracer in or let-er or any other combination of tools.