Transcript from the "Closures & Explicit Blocks" Lesson
[00:00:24] So let's say you have some example, like you're setting up some click handlers on some buttons. It's like button+i .click, and then you're setting up these click handlers that are supposed to print out
>> Kyle Simpson: What's been clicked, okay? Sounds all well and good, until you realize there's only one i when we use a var.
[00:00:52] If we have a var here, there's only one i, so every one of those click handlers is gonna close over the same i. They're all gonna print out i 10 cuz that's the value of i at the end of this for loop, unless it gets changed to something else, right?
[00:01:26] Functions or arrow functions, either way, they all behave lexically with closure the same way. They're gonna close over that i value the way that we expect them to close over the i value. So if we click button three, it's gonna say i three.
>> Speaker 2: Is that only if you have the let keyword within the for loop?
>> Kyle Simpson: It's only in the for header that it will automatically create it. Another way of getting around that, if you wanted to use a var here for some other reason. Another way of getting around that is to make your own inside of the for loop, so let j = i, and then close over j.
>> Kyle Simpson: Either way you'll accomplish the same thing, okay? So block scoping can actually be useful for dealing with closures, and in the cases specifically of for loops.
>> Kyle Simpson: One last thing before we move on to const. Again, stylistic suggestion here. There was a form of the let keyword in Firefox more than a decade ago and it looked like this.
[00:02:28] Instead of having a let keyword like let x = 2, you did let x = 2 with parentheses and you made a block. And now this block had x inside of it. It's called the let block form instead of the let declaration form. I actually think this one is more preferable, syntactically speaking, because what we've done now is create an explicit block for no other purpose than being a scope.
[00:02:55] The let declaration is actually an implicit form because it hijacks an existing if or for loop and turns it into a block of scope. Meaning if you have a big old thousand lines of code, and you're trying to figure out is this thing a scope, you're gonna have to scan through every line of the code and see if you find a let somewhere.
[00:03:13] It's implicit, right, it's more mental tax for you to juggle to try to figure out. It's not impossible. It's just more work for you to do and I'd like you to do less work if possible. And I'd like your readers to do less work as well. So I think the explicit form here is a little bit more preferable because it makes very clear this isn't doing anything other than being a scope.
[00:03:32] Even if I was doing that inside of an if statement, I would still think having an explicit block is better than an implicit block, okay? It's my own personal taste. Unfortunately, this particular form was rejected by TC39, not just rejected like nah but rejected with prejudice, like you are a bad person Kyle for asking us to put this in the spec.
[00:03:58] And I'm not making that up. There was a little discussion thread where they yelled at me for asking to put this in the spec. So this doesn't exist in the spec, but the next best thing is to do what we've done forever in every other language which is to just open up a curly brace pair and make an explicit block for that scope.
[00:04:32] But in all other cases I think being more explicit is more helpful. So this is a syntactic form that allows us to do an explicit block, and yes by the way, I intentionally put it all in the same line. Stylistically cuz I want all of my declarations to be at the top.
[00:04:48] Because there's this thing in ES6 called the TDZ, the temporal dead zone, I'm not making that up, where if I had let x = 2 and before it I tried to say console.log(x), which sounds silly but it happens all the time. We accidentally try to reference something, some other programmer comes in and puts it in a piece of code.
[00:05:08] This is actually gonna be an error. You're gonna get an error because x doesn't actually exist in an initialized form that we can use yet, okay? So because I don't want you to run across TDZ errors, I think you ought to put your declarations all at the top of your blocks.
>> Speaker 2: Two questions now. So with the temporal dead zone, it actually throws, right? It's not like x is undefined, it actually throws an exception.
>> Kyle Simpson: No, it literally throws an exception. It's a reference error but it's called a TDZ error by the spec.
>> Speaker 2: Right, and then my previous question would have been, did Firefox remove their old form of let then?
[00:05:45] Or is it still in Firefox today?
>> Kyle Simpson: I actually don't know whether Firefox removed it. Normally, Firefox reserves the right to leave stuff in, but let's just ask whether or not they did or not.
>> Kyle Simpson: Looks like they probably removed it.
>> Kyle Simpson: I guess that discussion thread was pretty clear.
[00:06:19] It's never gonna happen so they thought, why not go and remove it?