 I'm not going to adjust it. It's straight. It does here, isn't it? I mean, it doesn't look it. It really does not look straight. There it is. Yeah. Camera one. And again, apparently neither do we. Baaaaaame. So we had a chat in the office a couple of weeks ago. I mean, OK, we have today as well, but I'm talking about a specific chat we had. Specifically, where we were looking at code like this. So we've got your all scripty tag here. Scripty tag, always good. A couple of variables in there. Avar, const, all right, cool. And again, but this time, it's a module. It's a module, and then the question we were posing each other was like, well, what can be accessed? What is available in the third script tag, which in this case is a module tag? Well, OK, now the only reason it's a module tag, right? OK, you're now making me go on a tangent already. The only reason it's a module tag is because if it was normal script tag, these would not run in this order. Oh, because? Modules are deferred. Buy it implicitly. Yes. So if it was a script tag with defer, what is it? It's ignored. Oh, because it's inline. Deferred is ignored on inline script tag. Yes, it is. Today you learned. There we go. Good tangent. Now we've got that out of the way. Yes, the only reason I put type module on this is. So we have a good order. They actually execute an order. They appear on the snippet, right? Exactly. Good. So you actually did a Twitter poll. I did a Twitter poll. It was not like this exactly, but related. Very similar. It had some of the same things. And we thought of doing an episode. Yeah, like I wanted to write it. I wanted to tweet this. I did a poll 24 hours. I wanted to tweet the solution. And I said, no. No, you don't. That's precious content. Hold on to that content. And I will take credit for it again. So this time we actually have semi-good content. Exactly. Well, let's not say that. Let the audience decide. Yes, let the comments decide if this is actually good. I don't know that the comments decide, mate. OK. So I figured let's start by talking about how scoping works in JavaScript. Yeah, I mean, that's really what this is all about. Exactly. But we'll go back to the start. So back in olden times, ye olde JavaScripty. This is like ES3. ES3 time. The only way you could create a variable was with var. Yes. Which is good because that's what var stands for, a variable. It is. But you could also create functions. Yeah, that was in ES3 as well. Yeah, we had those. But they behaved in very, very similar ways. So a var or a function would be scoped to the parent function or the global if there wasn't one. So here we got one. And I thought you had two boundaries that existed at the time, like either function or you had the global. Hold on to that. Oh, boy. Oh, boy. OK. So we've got, yes, a var one that is on the global, two on the global, and we've got three. It's in a function. So it's scoped to the function. And four is also scoped within two. So you couldn't call four out of here. That wouldn't work. So if you did something like this, if you did var five inside an if and a function six, they would actually now exist within two. Within two. So you'd be able to log them. Because blocks were just not a scoping mechanism. So you could naively say that the only thing that has a scope in JavaScript in this era was a function or the global. That's what I would have said. That is what you would have said. There are two cases where that was not true. It still isn't true. OK. So. And so I will give you a clue that these are not places that you can create variables as such. But there are places where an identifier has a scope, which is smaller than a function. Ooh, that's oddly. The phrasing was so oddly specific. Well, I'm trying to help. And I love putting you on the spot. I do this a lot in the videos. And it's stuff that I wouldn't get either. Technically, what about for loops? Go back. If I had to for var i equals zero, is that i available after the for loop? Yes, it is. So that would go up into the parent scope. And we've done a video about less. Well, I was letting const, right? I wasn't sure if that was also some weirdness. No. And I didn't. I thought this was going to be a short video, but I think now we should just sit here until you get it. Until a figure. You name every bit of construct in ES3. Shall I just tell you? Yeah, you can tell. Because I wouldn't have got this either. Go on then. Catch. The error. Should I try catch the thing? Yes, we had that. We had that in olden days as well. Thank you very much. But this error identifier is only available in the catch. Interesting. OK. So this bit I did know, or I knew catch had a scope associated with it. But actually, because I'd heard that, it misled me to think that variables would be scoped within it. They're not. You do have variable in here. Those, again, would bubble up to the outer function or scope while. But the error stays within the catch block. And the other one, which I will forgive you for not knowing, is width. Is that still a thing? Well, it was in ES3. I think. I mean, is it still a thing? I think in strict mode, it stops you using it, but don't hold me to that. What does width even do? Right. What it will do is it will. It's just like a replacement for scope block. A block scope. Well, so it will take all of the properties of object and create local variables for them inside the width block, but only inside the width block. So it is, I believe. And again, don't hold me to this. I believe it's the only thing in JavaScript where the variables that can exist within it are not deterministically. You can't just do it apart. You can't figure that out at parts time. I guess the other part is eval. And that's why both of these things, like if you're using eval, if you use width, a lot of the performance optimizations that engines have just go out the window. Because they can't. The fact is, since I said I got this means that it's a thing. It is a thing. It is a thing. So that's the two things that have a different scope. But then, right? Oh, yes. Special behavior. Special magic behavior. Oh, boy. How is this the hoisting? No, this is not the hoisting. The hoisting is like, ah. So it's going to be a short video. No, I'm not going to talk about hoisting. People can search for hoisting. I think we talk about hoisting once. Fine. Good. We'll just put a list. It's all my favorite words. Hoisting. Hoisting. Hoisting source. If you have a global variable with var or function, it does a magic thing in that it will also, well, it will put it on the global object. How's that magic? I thought that's the thing. That is the global, right? Well, you say that. But that's not because you're used to it, right? It's actually weird. Come on, it's weird. But I thought that's just the whole premise of JavaScript. You have this, that your global scope is also tied to a specific identifier. But maybe that's just me coming into JavaScript too late where all these things have already been figured out. Well, hold on to that. I would say just as an aside, yeah. So self is referring to the global object. That's what it is in the browser. Yes. You also have a window. That's only in windows. But you're currently talking ES3, right? Because this is already different. Well, no, your global object is self today. Your global object is window if you're in a document. Global is the global in node. And the new bit is global this, which is trying to standardize across all of those. Because it turns out we couldn't standardize on any one of these because people use it to identify if I'm running it. I thought there was a case where self and window might not be equal. Maybe I'm wrong. That's not, that's not, that's not, that's not. I definitely don't know off the top of my head. OK. So yeah, so this is the magic case. It's weird and magic that stuff in the global goes on. Is self still window in module script text? Yes. OK. Then I'm wrong. That much I know. So we got some new stuff. We got new stuff. New JavaScript stuff arrived. Along with Va, we got some new ones, const and let. Which we talked about on the show before. And these have more sensible scoping, should we say? More, yeah, less unorthodox. Specifically block level scoping. So inside this if, as we've already seen, one is going to be thrown into the parent scope, be it a function or a global. Whereas two will only exist inside the if block. And same with three. And that's true for while for two. There's any curly braces, right? In fact, you can do that. Ah, see, there you go. And there you go. And it works. So that's kind of how you think about it. If it's got the curly braces, two and three are going to do the right thing inside there. So I was playing around and it suddenly occurred to me. Yeah. What's going to happen there? This should not throw. I think this will work. What do you think will happen? Because the var one will bubble up to the containing scope, which might be the function of the global scope. And then the const one will shadow that. Because shadowing is a thing anyway. Yeah, no. That is not what happens. Generally, when I thought about this, I didn't know. And I agree with you, run time, this could be a thing. But it fails at parse time. It sees two identifiers being declared within the same scope, even though var will do something inside differently. So it will actually throw. Yes. Interesting. And I guess it might be down to that if you have const one in a block, you cannot, previous to that, refer to one in a parent scope. It will tell you you are trying to use the thing before it is declared. So I think that's where this comes from. I see. But if I move the var outside the curly braces, that's fine, right? Yeah, that's fine. Interesting. OK. So there we go. That was a pointless piece of information, but it's something I learned while making the slides for this. So I guess the first part of the question, really, is we've kind of seen these vars, we've seen these consts things. But across two script tags, how does they work? Yeah, how does it? How does they work? One goes onto the global, as we've seen. We are pretty sure about one at this point. It works. Two is already slightly a bit more questionable. Yes. So you could also do soft at one, fair enough. And yes, the questionable one is two. That was a good sentence to say, wasn't it? Questionable one is two. Questionable, the one that is questionable is two. Now, there's no good way of saying that. Do you know what? I went back and forth on the variable naming here, between just doing A, B, C, and D, or one, two, three, and four. And I felt like I'd done the right thing. Now, I realize I did not. OK, it's very confusing. Well, it's better than foobar buds. So that's what I started with, and I ran out with foobar, yo, I mean, there's crooks and all. I don't remember. I don't remember after that. Especially useless tangent. So, two. The thing is, I did the quiz. I looked at the solution. I don't remember. Really? Great. Excellent. So when you do const two at the top level, like for, it goes on the global scope. It goes on the global scope. OK, cool. So this works, because the two scripts share a global scope. So contrary to what I think most people on Twitter believed, a script tag is not equivalent with curly braces. It's not a scope. Exactly. Correct. But this is where things get different. Right. Yes, I remember now. And so, yes, it too does go on the global in terms of like ECMAScript. It is a global. But what it doesn't do, is it doesn't do the weird hooking it into the global object. Because technically, the global object is under the actual global context. It seems like that's how I understood Yang, one of our V8 engineers who wrote an explanation. Yes, yes, and sort of. In some ways, the global that one and two exist on are the same. In some ways, they are in some ways, they aren't. Because same again, if you did var one equals true and var const one equals true, you could think if they're sitting at a different level, it should all be fine, but it's not. It will stop you from doing that. So it's one global, except one. So I guess standard that it actually is magic, like you said, that the one gets additionally patched into the global object, which is something else from the global context. Yes, it's kind of object record thing in ECMAScript, and that's how that works. So yes, so there we go. One works, self.one works, two works, self.two will be undefined. It will be undefined. So there we go. OK. But what happens here? What changes? Well, I did know that module scripts don't bubble up to the global. You're sort of right. If you create, imagine that they're wrapped in a function. Right, so if you have a free floating var in a script module tag, that will not end up on the global context or the global object. Correct. So it will, you still have access to the global. But you can still access documents and blah, blah, blah. But if you want to put something on the global, you have to do it manually and explicitly. Absolutely. That is true. So that, I guess, takes us to this. The question on. The question on. The question on how the teacher used to say question used to wind me up. I mean, it's just wrong, isn't it? And do you know what, as a teacher, you say that word a lot. So it's really frustrating. This question. All right, so we know now that 1 and 2 will be, will, oh, no, now, they know that. Well, let's do the rest of the episode without actually saying proper words. That's fine. All right, so 1 and 2 are on the global context. The global context. But no, the lookups also happen on the global context. So this will work. So 1 and 2. 1 works. Self on works. Self on works. 2 works. Self.2 will be undefined. Self.2 will be undefined for the reasons we did before, because even though it's in a script module, it accesses it in the usual way. That will throw. That will absolutely throw. Yes. That's a pause to remember. Yes, because we treat module as if it's wrapped in a function. It's got its own kind of scope. So this will actually be an undeclared variable. Undeclared variable. Self.3 would be still undefined, because that's different. That doesn't throw. Looking up. A property is fine. So if you're undefined, it wouldn't throw. For. Same. Would also throw. Yeah. And that is it. That is how scopes work in JavaScript. I mean, you say now you understood all the patterns. If you rely on variables being passed in between script tags, implicitly, probably, well, in that pattern. There are cases you would do this, because if you've got a, like you're doing a server render thing, but you also want to dump the initial set of data into a script tag, that is someone where you will want to do. I'm saying that if you want to do that, make it as explicit write self dot blah, blah, blah. Oh, interesting. Yeah, OK. Because don't rely on these implicit rules, because then everybody will look at this and have to go, oh, I don't remember how the details were of these global context scoping rules. I would actually agree with that. I think the whole thing about, well, there's a reason why Const 2 doesn't end up on the global object, because it's weird. And also, we kind of want to stop putting everything on the global object, right? Because it's been kind of polluted over time anyway. So let's only make that happen when it's a conscious choice by the developer to actually write down self dot blah equals fine. And we do see that with future JavaScript as well. Things like async functions generate as all of that. They're functions. They still behave like functions, but class behaves more like constant let, in that it will be block-scoped and not do the global thing as well. It's something I looked up in the train this morning thinking, so I might ask that. So I bet it wasn't my stuff. You didn't ask that, so I just thought I'd crowbar that little fact in, so I feel fulfilled. Right. Did you use all your knowledge you looked up now? Is there something else you want to sprinkle in? That is all the knowledge I had to give you in this episode. Done. Thank you very much for this insightful report. I've kind of gotten used to wearing my glasses for this shoot. And now I'm going to get to what point I can confidently pull out the rustle and go, like, and do you see that? Well, that's how I've noticed, actually, I've got, because I wear glasses at, you know. You have the two stripes of doom. They're really, my new glasses are actually really harsh like that. And so I've been thinking, if I just keep wearing them, it's going to get better.