Speaker 1: Hey, folks, welcome back to another episode of JavaScript Jabber.
Speaker 2: This week, on our panel, we have.
Speaker 3: Dan Spear Hello from Tel Aviv, and.
Speaker 1: I'm Charles Maxwo from top Endevs. This week, we're gonna
Speaker 1: be talking about what's new in JavaScript. It's a new year.
Speaker 1: There's a bunch of stuff that came out last year
Speaker 1: or so, and so Dan was pointing them out to me,
Speaker 1: and that's what we're gonna talk about today. So, Dan,
Speaker 1: I know you have a list. I don't have the
Speaker 1: list in front of me, so I.
Speaker 2: Will let you just.
Speaker 1: Yeah, I'll let you steer the ship and I'll.
Speaker 2: Provide the color commentary.
Speaker 3: Yeah. So it's been a while since we've spoken about
Speaker 3: what's new in JavaScript. You know, everybody's talking about what's
Speaker 3: new in frameworks, what's new in CSS, what's new in HDMO.
Speaker 3: But the JavaScript, you know, there was this period of
Speaker 3: time where things are coming out, you know, fast and furious,
Speaker 3: and then it seemed like everything kind of settled down.
Speaker 3: But turns out that you know, new features are being introduced.
Speaker 3: So I thought it would be worthwhile to talk about it.
Speaker 3: We actually spoke about it a year and a half
Speaker 3: ago in episode of five ninety and it's interesting to
Speaker 3: contrast what has moved forward and what hasn't. So, first
Speaker 3: of all, for our listeners, for anybody who may not know,
Speaker 3: there's this thing which is the JavaScript standard but is
Speaker 3: not actually called JavaScript. It's called ekmascript instead, which Brendan Iike,
Speaker 3: the creator of JavaScript, has likened to a skin disease.
Speaker 2: It's really easy to remember too. I mean, EKMA script
Speaker 2: just rolled.
Speaker 3: Roll yeah, rolls off the tongue. EKMA is actually the
Speaker 3: EKMA International is a standards organization. It was originally the
Speaker 3: europe In Computer Manufacturers Association, but then they just decided
Speaker 3: that it's EKMA and you know, not the credentials anymore.
Speaker 3: But so why is this standard called ekmascript rather than JavaScript?
Speaker 3: I mean, the fact that it happens to be handled
Speaker 3: by the ATMA organization should not have changed the name
Speaker 3: of the language, or at least the standard of the language.
Speaker 3: And the reason is that they don't have the copyright
Speaker 3: to the JavaScript name.
Speaker 2: That called trademark technically, but yes.
Speaker 3: Yeah, it's a trademark and it's being held by Oracle exactly.
Speaker 3: The name escaped me all of a sudden, and it's
Speaker 3: a funny story. Because in case you know listeners don't know,
Speaker 3: they probably don't. JavaScript was created in by Brendan Ike
Speaker 3: in Ten Days of Glory back in nineteen ninety five
Speaker 3: while he was working at Netscape. They were working in
Speaker 3: corporation with Sun, which was this the creators of Java,
Speaker 3: and they they had this kind of corporation where JavaScript
Speaker 3: was supposed to be the scripting language in the browser
Speaker 3: and Java was supposed to be the actual heavy duty
Speaker 3: programming language in the browser. That didn't happen. But what
Speaker 3: did happen was that Son ended up with the JavaScript trademark,
Speaker 3: and then.
Speaker 2: Because they owned the trademark to Java.
Speaker 3: To be honest, I'm not sure either because of that
Speaker 3: or because that was part of the deal of their
Speaker 3: corporation with the Netscape. Either way, they ended up with
Speaker 3: a trademark, and then they were bought by Oracle. So
Speaker 3: now Oracle holds that trademark and they've literally done nothing
Speaker 3: with it. So there's this new movement now to actually
Speaker 3: free that trademark from Oracle. They've actually reached out to Oracle,
Speaker 3: They've reached out to the governmental body that's responsible for trademarks.
Speaker 3: There's an online petition that everybody can sign at JavaScript
Speaker 3: dot tm fitting url. I signed it, and I encourage
Speaker 3: our listeners to sign it, and hopefully eventually it will
Speaker 3: be released. This is actually being led by Ryan Dahl
Speaker 3: from Dino, who we've interviewed a few months back. So
Speaker 3: he wrote an interesting blog post about it. We can
Speaker 3: link to it. He gives the entire history and everything.
Speaker 3: I hope it's released and we can finally call it
Speaker 3: JavaScript rather than ekmascript. But be that as it may.
Speaker 3: That's the name of the standard and it's being handled
Speaker 3: by a committee within EKMA called TC thirty nine.
Speaker 1: And TC I was gonna say, if you're wondering what
Speaker 1: the cryptic name, TC thirty nine is literally technical committee
Speaker 1: or something like.
Speaker 3: That, exactly, it's Technical Committee thirty nine. Their whole bunch
Speaker 3: of technical committees within EKMA, and that's the number they
Speaker 3: got and they have this whole process of how to
Speaker 3: introduce features into the JavaScript language. Originally this process had
Speaker 3: forced five stages sorry, zero through four, because well, you know,
Speaker 3: everything should be zero based. But now they've actually added
Speaker 3: an intrim stage two point seven, so now they have
Speaker 3: six stages and to run through them really quickly. Stage
Speaker 3: zero is basically it's a new proposal, it's not even
Speaker 3: really considered. Basically, you've had an idea and you've written
Speaker 3: down a note about it and sent it to the committee.
Speaker 3: That's more or less what stage zero means. It's hardly anything, really,
Speaker 3: but it's the starting point for all proposals in that
Speaker 3: are process by the committee. When the Committee decides to
Speaker 3: actually look at a particular proposal, it moves to stage one.
Speaker 3: That means that that proposal is under consideration. The committee
Speaker 3: expects to devote time examining and identifying the need for
Speaker 3: that proposal, what it's supposed to address or improve or fix,
Speaker 3: and basically compare it to other alternative solutions that might exist,
Speaker 3: and decide whether it's worthwhile to pursue. They need to
Speaker 3: identify somebody to champion that proposal. They expect an outline
Speaker 3: to be written and so and discuss algorithms and abstractions
Speaker 3: and semantics and so forth, all the good stuff. So
Speaker 3: that's stage one. Stage two is when the committee has
Speaker 3: chosen a preferred solution or maybe a few solutions in
Speaker 3: a in a particular solution space, but the design is
Speaker 3: very much still a draft and may change significantly before
Speaker 3: it's actually introduced into the language. The committee actually expects
Speaker 3: something to be developed and eventually introduced into the language.
Speaker 3: They're just not absolutely sure what it is yet and
Speaker 3: how exactly it's going to look. And at that point
Speaker 3: they expect, obviously the thing to be much better documented
Speaker 3: and you know, for people to start experimenting with it
Speaker 3: and actually have something real to examine. Now, they've introduced
Speaker 3: a new stage called two point seven because they didn't
Speaker 3: want to move stage two or stage three, and they
Speaker 3: wanted to put something in between. So stage two point
Speaker 3: seven means that the proposal is approved in principle and
Speaker 3: is currently undergoing validation. That means that maybe a browser
Speaker 3: manufacturer has put it behind a feature flag, or maybe
Speaker 3: there's a Babel plug in or something like. Somebody is
Speaker 3: playing with it, experimenting it and with it, and you
Speaker 3: can start seeing how it actually works and whether it
Speaker 3: actually feels like a good idea. Stage three is when
Speaker 3: the proposal has been recommended for implementation and no changes
Speaker 3: to the proposal are expected. In other words, they feel
Speaker 3: pretty confident that this is how it's going to be,
Speaker 3: but it's not yet part of the standard, and therefore
Speaker 3: backward compatibility is not yet required, which means that if
Speaker 3: somebody comes up with a better idea, or they they
Speaker 3: start suddenly discover a problem with it, they can battrack
Speaker 3: so they can even you know, move it back to
Speaker 3: a stage two or even to or two point seven
Speaker 3: something like that. And finally you've got stage four, which
Speaker 3: means that the proposal is feature complete and is ready
Speaker 3: to be included in the standard. Essentially, it means that
Speaker 3: it's effectively part of the standard. It's just that a
Speaker 3: new standard document has not yet been released. One is
Speaker 3: released once a year, So the proposals that are complete
Speaker 3: weight at stage four until they are included in the
Speaker 3: next release standard. And usually by the time they're in
Speaker 3: stage four, you actually find them implemented in browsers and
Speaker 3: you can actually start using them. So far, so good.
Speaker 1: M Yeah, it's funny too, because you're talking about this
Speaker 1: process and two things are going through my head, and
Speaker 1: one is it sounds complicated, but yeah, I mean, if
Speaker 1: you really think about the progression, it all makes sense.
Speaker 2: Right.
Speaker 1: The other thing that's going through my head is we're
Speaker 1: currently heading into a legislative session in the state of Utah,
Speaker 1: and so I've been going through the process that bills
Speaker 1: go through the past and they're going, I'm going, Wow,
Speaker 1: this is in some way simpler and in some ways
Speaker 1: more complicated than the political process.
Speaker 3: In certain ways, it has to be, because unlike the
Speaker 3: political process, these kind of standards are really set in stone.
Speaker 3: When something is added into JavaScript, it can never really
Speaker 3: be removed. Yeah, which means that we had better be
Speaker 3: really certain about adding it into the standard. And you've got,
Speaker 3: like I said, you've got the browser manufacturers on this committee,
Speaker 3: and they've got to really approve it and say, you know,
Speaker 3: this is something that we can actually implement. You know,
Speaker 3: somebody might have this great idea, but implementing it would
Speaker 3: turn JavaScript on its head. Then obviously the browser manufacturers
Speaker 3: will push back and won't approve it.
Speaker 2: Yep.
Speaker 3: So let's put it this way. The attitude is better
Speaker 3: safe than sorry, and that's a good attitude to have
Speaker 3: in the context of language standard, especially a languagelike JavaScript.
Speaker 3: Where As I said, once something is added, it can
Speaker 3: never be removed.
Speaker 2: I really wish that our legislators would do better safe
Speaker 2: than sorry. Let's think a little more deeply about this
Speaker 2: before we pass it or not? Right?
Speaker 1: Yeah, but yeah, I completely agree, and I think it's
Speaker 1: good context that JavaScript has always gone way out of
Speaker 1: its way to be backward compatible. I'm sure there's sometimes
Speaker 1: where there was just something that they had to kind
Speaker 1: of roll back, but.
Speaker 3: Actually, the one time that I can think of where
Speaker 3: effectively things were rolled back was they introduced strict mode.
Speaker 3: And even then they introduce they roll them back by
Speaker 3: introducing strict mode, So if you're running outside strict mode,
Speaker 3: they're still there. They wanted to roll back, for example,
Speaker 3: the with keyword, and I won't get into the details
Speaker 3: of why it turned out to be a bad idea
Speaker 3: in the context of the JavaScript programming language, but they
Speaker 3: couldn't remove it, and so instead they kind of rolled
Speaker 3: it back by making strict mode more and more the
Speaker 3: common way in which JavaScript work and in strict mode
Speaker 3: with does not exist. Right.
Speaker 1: Yeah, And if you're wondering, if you're if you're newer
Speaker 1: to javascripts and you're saying, what what what is strict mode,
Speaker 1: don't worry about it.
Speaker 2: You're using strict mode.
Speaker 3: Yeah, just so you know, you know, we mentioned it,
Speaker 3: so we might as well provide details. You can explicitly
Speaker 3: enter strict mode by having the use strict string at
Speaker 3: the top of a scope or the top of a file.
Speaker 3: You can't actually ever exit strict mode. You only enter
Speaker 3: strict mode. And you enter strict mode by default in
Speaker 3: ekmascript modules. So if you implement a module, it's strict
Speaker 3: mode by definition. In HTML, that's if you have a
Speaker 3: script tagged with the type equals module, it's strict mode
Speaker 3: by default, and then you can do module things like
Speaker 3: imports and stuff like that. You also strict mode by
Speaker 3: default in classes, because again, classes are kind of a
Speaker 3: new type of a scope, and it makes sense to
Speaker 3: be strict by default inside classes.
Speaker 2: Yeah.
Speaker 1: I think most people working within the context of JavaScript, though,
Speaker 1: they're working under some system that puts them in strict
Speaker 1: mode without them.
Speaker 3: Yeah, because they're building hopefully they're building ekmascript modules these.
Speaker 1: Days, yeah, or React projects or you know, whatever other
Speaker 1: framework or library you're using, generally use modules, and so
Speaker 1: you're generally put into this box anyway.
Speaker 3: And I really can't think of any other occurrence where
Speaker 3: something was effectively removed out of JavaScript, so you know,
Speaker 3: it's interesting. Yeah, anyway, So let's talk about a couple
Speaker 3: of these enhancements and proposals. But before we dive into them,
Speaker 3: it's really worthwhile to highlight the fact that none of
Speaker 3: them really significantly or maybe even at all, change the
Speaker 3: JavaScript syntax or semantics. So you've got nothing new like
Speaker 3: the arrow functions syntax or let or cons or stuff
Speaker 3: like that which really changed the way that JavaScript kind
Speaker 3: of worked. Well, there is one towards the end, but
Speaker 3: it's still at stage three, and we'll see if we
Speaker 3: make it all the way to that one. But all
Speaker 3: the rest can are better described as being part of
Speaker 3: a quote unquote JavaScript standard library. They've added new object
Speaker 3: types and new methods or functions that are built in
Speaker 3: that you can use instead of let's say, importing some
Speaker 3: NPM module that would implement them. So we've got more
Speaker 3: standard functionality being provided out of the box by the
Speaker 3: JavaScript runtime environment itself, be it the browser or vi
Speaker 3: it node or whatever.
Speaker 1: Yeah, so what I'm hearing is is that if you're
Speaker 1: using these feature, you may be already be using these features.
Speaker 2: They're just now official standard kind of stuff.
Speaker 3: Yeah, you might have there's a good chance that you
Speaker 3: might have imported such functionality before. Now it's built in
Speaker 3: and you do need to import it anymore. Kind of
Speaker 3: like the browsers started providing fetch as a built in function,
Speaker 3: and you didn't need something like an axios anymore. Ye.
Speaker 3: So the first one I would like to mention is
Speaker 3: something that's actually five years old. It's from ES twenty twenty,
Speaker 3: and it's called promise dot all settled, and as its
Speaker 3: name implies, it waits for all this provided promises to
Speaker 3: be settled. Now, you know, it's very common when working
Speaker 3: with promises to need to wait on a couple of
Speaker 3: promises simultaneously, effectively in parallel. And when most developers need
Speaker 3: to do that, I see most of them reaching out
Speaker 3: for promise dot all and just using promise dot all.
Speaker 3: But what they might have not considered is the fact
Speaker 3: that promised dot all short circuits on a rejected promise.
Speaker 3: So promise dot all receives an area of promises and
Speaker 3: it waits in parallel on all of them. It returns
Speaker 3: a promise that resolves when all the provided promises resolve.
Speaker 3: But if even one of those promises reject, then the
Speaker 3: return promise immediately rejects. And that may not be what
Speaker 3: you're looking for. It may be, but it may not be.
Speaker 3: Sometimes you actually want to wait on all the promises
Speaker 3: provided until they are all of them either resolved or rejected.
Speaker 3: In other words, all of them are settled, and hence
Speaker 3: the name of the method, all settled.
Speaker 1: Right, So let me see if I can restate this
Speaker 1: in a different way. So, if you promised dot all, Yeah,
Speaker 1: if one of them rejects, you get rejected.
Speaker 2: I media doesn't.
Speaker 1: Yeah, but it doesn't tell you that they've all finished
Speaker 1: waiting for whatever it is that they're waiting for, And
Speaker 1: so effectively the all settles it does more or less
Speaker 1: the same thing. But if you have one of them
Speaker 1: that's still waiting for whatever, you know, whether it's going
Speaker 1: to reject or fulfill or anything else.
Speaker 3: So think about the simple scenario. Let's say you have
Speaker 3: two promises, sorry, let's say even three promises, and you
Speaker 3: pass the area of the three promises into promise all.
Speaker 3: Let's say the first one resolves, that's great, and then
Speaker 3: the second, then the other two are still pending, and
Speaker 3: then the second one rejects. Then it will immediately return
Speaker 3: with a reject. It won't wait on the third one
Speaker 3: to either resolve or reject, and it won't also tell
Speaker 3: you that the first one resolved. It will just tell
Speaker 3: you that, hey, this thing rejected, okay. Whereas with promise
Speaker 3: all settled, what you get back is an area of objects.
Speaker 3: First of all, it waits on all three, so even
Speaker 3: if the second one rejected, it will still continue to
Speaker 3: wait until the third one completes, and then it will
Speaker 3: return an array of objects, and each object has a
Speaker 3: field that indicates whether or not it resolved or rejected.
Speaker 3: So I wanted to have this open, and I forgot.
Speaker 3: I just posted a link to Yeah, MDN is always there. Yeah,
Speaker 3: MDN is always the best. So it basically returns an
Speaker 3: array of objects, one per each promise it had. Each
Speaker 3: element of those rays is an object where and it
Speaker 3: has a property called status, and that status could be
Speaker 3: either fulfilled or rejected. It has it. If it's fulfilled,
Speaker 3: then it will have a field called value with the
Speaker 3: resolved value, and if it if it was rejected, it
Speaker 3: would have a field called reason with the appropriate rejection reasons.
Speaker 3: So this way you can look at all the promises
Speaker 3: and see whether they resolved or rejected and what they
Speaker 3: actually returned. And as I said, in a lot of cases,
Speaker 3: that's actually what you want rather than just promised dot all.
Speaker 3: But a lot of people are not familiar with it
Speaker 3: and use promise dot all when they should have actually
Speaker 3: used promise all settled.
Speaker 1: So MDN makes it look like because it calls promise
Speaker 1: dot all settled, you pass in the array and then
Speaker 1: it calls dot then so does it operate as a
Speaker 1: promise as well?
Speaker 3: Yeah, yeah, it returns a promise that resolves to that
Speaker 3: array of objects.
Speaker 1: Right, Yeah, I just wanted to, you know, clarify because
Speaker 1: you said it returns that, but it does. It's a
Speaker 1: promise that resolves to that array of so it has
Speaker 1: to wait for everything to finish exactly.
Speaker 2: That's cool.
Speaker 1: So I'm going to ask another question that's not about
Speaker 1: all settled. But you said this is from five years ago.
Speaker 1: So when you say that we're talking about new things
Speaker 1: in JavaScript, are these things that are now generally implemented
Speaker 1: or are these just things that, hey, these have passed
Speaker 1: in the last however long and people ought to know
Speaker 1: about them, or what's your criteria for making the list?
Speaker 3: Well, first of all, this is the oldest one. Everything
Speaker 3: else that I'm going to be talking about is newer
Speaker 3: than that, And I guess my criteria was relatively new
Speaker 3: things that our listeners might thought known about. Now I
Speaker 3: think that things that are actually already part of the
Speaker 3: standard are generally much more interesting that things that are
Speaker 3: not yet part of the standard. I mean, you know,
Speaker 3: things that are not part of the standard might be
Speaker 3: really cool. Usually they often push the envelope a lot more,
Speaker 3: which is one of the reasons that the committee is
Speaker 3: kind of hesitant about adding them actually into the language.
Speaker 3: But I think that when you've got a functionality that
Speaker 3: can actually be used and provides real value, that's more pertinent,
Speaker 3: let's say, than some pie in the sky that might
Speaker 3: never actually arrive.
Speaker 1: Right, So these are probably just hidden gems that you
Speaker 1: may not have known got added to the language.
Speaker 3: Exactly over the last five years, I guess. The next
Speaker 3: one is from ES twenty twenty two, so it's almost
Speaker 3: three years old, and it's the dot at method on arrays,
Speaker 3: strings and type rays, and you basically give it an
Speaker 3: index and you get back the item. So it's really
Speaker 3: like using the square brackets in a lot of ways.
Speaker 3: And you might ask yourself, well, why do I need it,
Speaker 3: Why don't I just use the square brackets, And the
Speaker 3: reason is that you can also provide it with negative
Speaker 3: numbers and then you're indexing from the end. So if
Speaker 3: you do dot at on an array and pass in
Speaker 3: minus one, you're looking at the last element in the array.
Speaker 2: Interesting.
Speaker 3: Now, that's actually how various other program earring languages actually work.
Speaker 3: So in other programming languages you might have been able
Speaker 3: to have the minus indexes in the square brackets themselves,
Speaker 3: but you can't do that in JavaScript because that's not
Speaker 3: how named properties work in JavaScript. And in JavaScript you
Speaker 3: could legally legally have a minus one property. Uh, so
Speaker 3: you couldn't use that. And the funny thing is that
Speaker 3: this negative index has actually worked with the dot slice
Speaker 3: method for a long time, but then it would always
Speaker 3: return an array, right, And with dot at you get
Speaker 3: that actual element from the array, which is just nice.
Speaker 1: Yeah, I've used other languages that do this with their array,
Speaker 1: so but they do it with the square brackets. And yeah,
Speaker 1: you're you're explaining why you couldn't do that and maintain
Speaker 1: backward compatibility with JavaScript.
Speaker 2: But yeah, this is this is really cool. I like that.
Speaker 3: Another one that's more of a you should use and
Speaker 3: probably don't is object dot has owned. Are you familiar
Speaker 3: with the has owned property? A method that so in
Speaker 3: JavaScript you can use there's the inoperator which tells you
Speaker 3: whether or not a property exists in an object. Objects
Speaker 3: in javas kind of work like property bags, and you
Speaker 3: can check to see whether a particular string is the
Speaker 3: name of a property in an object using the inoperator,
Speaker 3: But the inoperator also looks up the prototype chain, so
Speaker 3: it doesn't.
Speaker 2: Always say this, this is cool. I just looked it
Speaker 2: up and I am yeah. Anyway, go ahead.
Speaker 3: Now has owned property has existed forever as a way
Speaker 3: to check whether a property name exists in an object
Speaker 3: without going up the property chain. The problem with has
Speaker 3: owned property is that not all objects necessarily have it,
Speaker 3: because you need to have the object prototype in your
Speaker 3: prototype chain to actually have it, and it's not there
Speaker 3: by definition, so you might try to use his own
Speaker 3: property only to have it break because you're not actually
Speaker 3: your object doesn't actually derive from object prototype. So the
Speaker 3: safer way is to do object dot has own as
Speaker 3: this kind of a global method static method, and the
Speaker 3: first parameter is the object you want to test, and
Speaker 3: the second parameter is the name of the property you
Speaker 3: want to check. So it's just a safer way. So
Speaker 3: the preferred way to check whether or not a specific
Speaker 3: object has a particular property is not using his own property,
Speaker 3: which is what most of us do, but rather using
Speaker 3: object dot has owned. Yet I've don't recall ever seeing
Speaker 3: code actually work like that.
Speaker 1: So right, So if you've this for example, could tell
Speaker 1: you if you've over ridden a property.
Speaker 2: Right, you've written your own function For.
Speaker 3: A lot of people, Yeah, a lot of people use
Speaker 3: JavaScript object objects as dictionaries. You know. Ideally I think
Speaker 3: they should be using the map object type, but a
Speaker 3: lot of people still like using simple objects because you know,
Speaker 3: it's easy to confer to from Jason and so forth.
Speaker 3: And you want to check whether, let's say, a certain
Speaker 3: property exists in a Jason object or not, so you
Speaker 3: might use check using has own property. You should actually
Speaker 3: check whether or not it exists using hazone.
Speaker 2: Gotcha.
Speaker 3: So those are two things that were added almost three
Speaker 3: years ago in EES twenty twenty two. Dot at an
Speaker 3: object has owned relatively new. I guess mostly not so
Speaker 3: much you used, but they're there and they're useful, and
Speaker 3: I guess people should be using them more. Moving on,
Speaker 3: Yes twenty twenty three. Here's a nice one that a
Speaker 3: lot of people I think might like, and this is
Speaker 3: find last on arrays. Sometimes you want to find the
Speaker 3: last element matching a particular thing rather than the first. Now,
Speaker 3: obviously you can do reverse and then find, but why
Speaker 3: reverse the entire array when you can just do fine last.
Speaker 2: Nice. It's funny because I'm I'm looking at the.
Speaker 1: Oh, it does have fine last in here, but it
Speaker 1: also had fine last index, of which I guess is
Speaker 1: related but not the same.
Speaker 3: Yeah, find and find last, return the actual value, find
Speaker 3: index off, and find less index off. Return the index
Speaker 3: of the found element.
Speaker 1: Right, and this this finds a matching element, right, So
Speaker 1: you can pass it a function and you can say
Speaker 1: if this returns true on the element, then Yeah.
Speaker 3: Let's say you want you have an area of numbers
Speaker 3: and you want to find the first one bigger than
Speaker 3: forty two. So you can pass in a function that
Speaker 3: compares the x. You know, you would do x errow
Speaker 3: x forty two, Yeah, exactly, and would find regular find
Speaker 3: you would find the first element greater than forty two,
Speaker 3: would find lass. You simply find the last item greater
Speaker 3: than forty two. Yeah, And like I said, usually what
Speaker 3: people would do is that they would reverse the array.
Speaker 3: And it's kind of silly to need to reverse just
Speaker 3: to find the last one, right. Speaking about reverse, the
Speaker 3: next things that I wanted to mention that came out
Speaker 3: in twenty twenty three are the change array by copy
Speaker 3: again talking about things that were in JavaScript that are
Speaker 3: a bit unfortunate but cannot be fixed because backward compatibility.
Speaker 3: We have certain methods that modify arrays in place. So
Speaker 3: for example, if you do dot reverse on an array,
Speaker 3: it reverses the array in place. Likewise, if you do
Speaker 3: dot sort, it sorts the array in place, and that's
Speaker 3: not how we want to work in a more quote
Speaker 3: unquote functional world. I guess they did it back in
Speaker 3: ninety five because for efficiency's sake, to avoid the extra locations.
Speaker 3: But you really, you know, it's you really want to
Speaker 3: avoid methods that modify objects in place if you can,
Speaker 3: if you can avoid it. So what they did is
Speaker 3: they introduced an alternatives, well not an alternatives, alternatives to
Speaker 3: these methods that create a copy. So instead of reverse,
Speaker 3: there's this new dot too reversed, and to reverse does
Speaker 3: not modify the original array. Instead it returns a new
Speaker 3: array which is reversed. Likewise, you've got the dot two sorted,
Speaker 3: which again sorts an array, but rather than sorting in place,
Speaker 3: returns a new sorted copy. And you should be using these.
Speaker 3: There's absolutely no reason. What I used to see are
Speaker 3: people copying the array by doing a dot slice and
Speaker 3: then doing a reverse on the copied array, And now
Speaker 3: they can just do too reversed or too sorted. There's
Speaker 3: also there's also a too spliced reminder splice. Unlike slice,
Speaker 3: it can be used to replace, to delete parts of
Speaker 3: an array and replace parts of an array. Too spliced
Speaker 3: does that, but instead of modifying the original array again
Speaker 3: returns a modified copy.
Speaker 2: Yeah, there's also a two sorted.
Speaker 3: Yeah, I mentioned already the two sorts and is Yeah. Yeah.
Speaker 3: The dot with is confusing because it's kind of not
Speaker 3: to something, So where did this come from? Dot with
Speaker 3: is like dot at, but it modifies the copy, so
Speaker 3: it modifies a particular item. You know. With dot at
Speaker 3: you could change the value of a particular item. With
Speaker 3: dot with, you give an index and a new value,
Speaker 3: and it replaced, and it creates a copy where that
Speaker 3: particular element you know, with that index has the new value.
Speaker 3: So you might have an array let's say with one
Speaker 3: two three, you do dot with one comma forty two,
Speaker 3: so it will become one forty two three.
Speaker 1: Yeah, and that I agree with you on this should
Speaker 1: be your default way to move through arrays. I mean,
Speaker 1: we we run into these problems all the time where
Speaker 1: you inadvertently change something that you didn't intend to, and
Speaker 1: so by doing things in this way, you'll avoid those
Speaker 1: issues unless you explicitly want to be changing that for
Speaker 1: a real good reason.
Speaker 3: Exactly, and especially because in JavaScript, when you pass arrays
Speaker 3: into functions or methods, you're passing the reference to the array, right,
Speaker 3: so you're actually passing the reference to the original array.
Speaker 3: And if that method then or function then calls dot
Speaker 3: reverse on the array that was provided to it because
Speaker 3: it needs a reverse copy for some reason. But use
Speaker 3: reverse instead of two reversed. It not only modifies the
Speaker 3: array for itself but also for whomever called it, which
Speaker 3: is totally unexpected behavior in most cases. Yep. So yeah,
Speaker 3: for sure going forward, always used two reversed instead of reverse,
Speaker 3: two sorted instead of sorts too, spliced instead of splice,
Speaker 3: and dot with whenever that makes sense. Continuing to move
Speaker 3: up the calendar, where you know we are now in
Speaker 3: twenty twenty five, let's look one year back twenty twenty four.
Speaker 3: We also got a couple of things. We got top
Speaker 3: level away and by top level. It means top level
Speaker 3: of a module. So if you're creating an ECMAScript module,
Speaker 3: you can have a weight outside of a function body.
Speaker 3: In the past, you could only use a weights inside
Speaker 3: a sink functions. Now you can actually use a weights
Speaker 3: outside but at the global scope as it were, but
Speaker 3: only inside modules. You might use it to maybe import
Speaker 3: some sort of a dynamic mode, do some sort of
Speaker 3: dynamic module import, or maybe get some configuration file or
Speaker 3: something like that. So you might want to do a
Speaker 3: fetch in order to get some configuration or something like that.
Speaker 3: But you really need to be careful with top level
Speaker 3: of weights because they block the module load. So if
Speaker 3: you've got one module weight importing a submodule and that
Speaker 3: submodule does a global a weight, then it blocks the
Speaker 3: module that imports it until that promise resolves. Is that clear?
Speaker 2: Mm hmm.
Speaker 3: Yeah.
Speaker 1: There's there's a really good example on the proposal itself,
Speaker 1: and I posted a link to that the TC thirty
Speaker 1: nine proposal, where essentially what they're doing is they're running
Speaker 1: the A weight within a function. That's kind of the
Speaker 1: So you create a function and then you call the
Speaker 1: function is effectively what you're doing with the A weight
Speaker 1: in it that's an acin function, and they've done it
Speaker 1: with an immediately invoked acin function as well as just
Speaker 1: a named function that they call that's an acing function.
Speaker 2: But yeah, yeah, I can see where this could be
Speaker 2: a foot gun or you can shoot yourself in the
Speaker 2: foot doing this, for sure, But I can also see
Speaker 2: the utility in it. Right.
Speaker 1: It's like, in order for this module to do anything useful,
Speaker 1: I have to have this other thing.
Speaker 3: Yeah. Without this data, I can't do anything. Yeah, so
Speaker 3: I really need to wait on that data before I
Speaker 3: can actually even finish loading. Right, But again, you should
Speaker 3: definitely be really careful about using top level of weight
Speaker 3: inside your actual code.
Speaker 2: Yeah, I definitely have a reason to be doing this.
Speaker 3: The next ones I want to mention, and they're really
Speaker 3: useful functions and have been available in a lot of
Speaker 3: other languages and are provided by libraries like low dash
Speaker 3: is object to dot group by and map dot group BI.
Speaker 3: Let's start with object group by. With object dot group by,
Speaker 3: you provide an array of stuff and the function that
Speaker 3: you invoke it sorry on on a collection of items,
Speaker 3: and you also provide a callback function which returns strings
Speaker 3: that describe each item in the sequence, and then it
Speaker 3: groups the items based on the string value. It's kind
Speaker 3: of difficult to explain, but very often we want to
Speaker 3: take a collection of stuff and group those things according
Speaker 3: to what they are. So, for example, I've got I
Speaker 3: might have like different types of different objects in an array,
Speaker 3: and they also all of them have let's say a
Speaker 3: different type which is a string. So I can group
Speaker 3: them according to that the value of their type property
Speaker 3: and have some return to one array of all the
Speaker 3: objects of one type, another area of all the objects
Speaker 3: of another type. It's instead of having to filter again
Speaker 3: and again and again, I can do it in one go.
Speaker 1: Yeah, this is something that I use pretty frequently in
Speaker 1: other languages as well. But and there's a really good
Speaker 1: example on the MDM doc that I just posted. But yeah,
Speaker 1: I mean they give a list asparagus, bananas, goat, cherries,
Speaker 1: and fish. They all have a type property of vegetable,
Speaker 1: fruit or meat, and then it tells it to a
Speaker 1: group by type essentially. And I'm not going to read
Speaker 1: the syntax for you. You'll have to go look at
Speaker 1: it because it's hard to just read out. But yeah,
Speaker 1: then it gives back an object that has properties of vegetables, fruit,
Speaker 1: and meat.
Speaker 2: And it's shoved those objects up underneath that.
Speaker 1: So it makes it really easy to, like you said,
Speaker 1: not have to iterate over at a zillion times if
Speaker 1: you're just sorting things or handling things based on on
Speaker 1: their type exactly.
Speaker 3: Now, the only difference really between object dot group by
Speaker 3: and map dot group by is whether or not the
Speaker 3: result is an object with the various fields or a
Speaker 3: map with the various entries. Some people would prefer to
Speaker 3: work with a map, some people would prefer to work
Speaker 3: with an object, so they can use either object dot
Speaker 3: group by or map dot group by, but the algorithm
Speaker 3: is essentially exactly the same.
Speaker 1: Yeah, it's interesting too because the so the on MDM
Speaker 1: for map dot group by, it hands it an array
Speaker 1: for the things that it's and it has the same
Speaker 1: list of things actually is object dot group by, but
Speaker 1: it hands it in an array for the thing that it's sorting,
Speaker 1: and yeah, it just gives back a map instead.
Speaker 2: So kind of interesting there.
Speaker 3: Now. The final one that I want to mention is
Speaker 3: one that's going to make a lot of our listeners
Speaker 3: kind of grown because a lot of people have really
Speaker 3: wanted something like that and have written a lot of
Speaker 3: boilerplate code to effectively implement this functionality, and so it's
Speaker 3: kind of nice to have it now built in out
Speaker 3: of the box. But on the other hand, I'm kind
Speaker 3: of worried that people will abuse it or misuse it.
Speaker 3: It's promise dot with resolvers. When we create a promise,
Speaker 3: only the promise can kind of resolve or reject itself.
Speaker 3: So you do new promise, you pass in a function
Speaker 3: to the constructor with the resolve and reject, and that
Speaker 3: function and the promised constructor invokes that function, and only
Speaker 3: that code has access to the resolve or reject. You
Speaker 3: can't resolve or reject a function a promise sorry from
Speaker 3: the outside. Now, what people do when they do want
Speaker 3: to be able to resolve reject a method of promise
Speaker 3: from the outside is then they actually copy resolve and
Speaker 3: reject into global variables outside the promised scope. And it
Speaker 3: kind of kind of feels wonky. Are you following what
Speaker 3: I'm trying to describe?
Speaker 2: Uh, not entirely.
Speaker 3: Let's say I have a promise, but I want to
Speaker 3: have some sort of an external event resolve it. So
Speaker 3: I do a new promise and I pass in the
Speaker 3: function that gets the resolve, but I can't resolve it
Speaker 3: from inside the promise. I want to have just an
Speaker 3: access to that resolve to resolve it somewhere else. So
Speaker 3: I copy the reference to the resolve and hand it
Speaker 3: over to somebody else, and then that somebody else can
Speaker 3: resolve me.
Speaker 1: Okay, sounds complicated, but I think I understand. Let me
Speaker 1: see how I can restate it, just so that I
Speaker 1: get it. So I have a promise for whatever reason,
Speaker 1: I'm not going to use the default you know dot
Speaker 1: then to resolve or you know dot what are the
Speaker 1: other ones like that?
Speaker 3: Or no, you're not, it's not exactly correct. Let's say
Speaker 3: you've got you do a new promise and you pass
Speaker 3: in a function with the resolve and that gets resolve
Speaker 3: and reject, and then you take the resolve and put
Speaker 3: it in window dot resolve, and you take the reject
Speaker 3: and you put it in window dot reject. Now you
Speaker 3: can call window dot resolve to resolve that promise. Uh huh.
Speaker 3: So you're copying that resolve method out of the promise
Speaker 3: into somewhere else, and that in the case I just
Speaker 3: gave it to an into a glow effective into a
Speaker 3: global but you can also copy it into a local
Speaker 3: variable in a in a scope, but you're just helping
Speaker 3: it out of the promise. And I've seen a lot
Speaker 3: of instances where people needed to do that for some reason.
Speaker 3: They want to be they have a promise, but they
Speaker 3: want to be able to just resolve it from somewhere else.
Speaker 2: Mm hm, I'm trying to think of why you would
Speaker 2: need to do.
Speaker 3: This, but there's there are good examples in the end
Speaker 3: in the m d N, but I've seen a lot
Speaker 3: of examples of such things. I've even seen example of
Speaker 3: something like that within reacts on code when they implement UH,
Speaker 3: when they they kind of throw promises to UH to
Speaker 3: do too in order to implement suspense. So it's implemented
Speaker 3: by throwing promises, and you need to be able to
Speaker 3: resolve those promises from the outside, so they also kind
Speaker 3: of hold on to the resolve and reject of the
Speaker 3: promises on the outside of the promise itself. Okay, So
Speaker 3: with resolvers actually does that for you in a kind
Speaker 3: of built in way. Instead of returning a promise, it
Speaker 3: returns an object that has three properties. A property called
Speaker 3: promise which is the promise, a property called resolve which
Speaker 3: is the resolver function, and a property called reject, which
Speaker 3: is the rejector function. Okay, So and you can destruct
Speaker 3: the return value and basically get the promise, get the resolver,
Speaker 3: and get the rejector.
Speaker 2: Right.
Speaker 3: So in cases where you need this kind of functionality,
Speaker 3: and as I said, I've seen this pattern used a
Speaker 3: whole bunch of times. It's now much easier and clean
Speaker 3: to do it because it's built into the language itself.
Speaker 2: Okay, so from what I'm because I'm looking at the
Speaker 2: proposal as well. Now, so essentially what you do is you, yeah,
Speaker 2: you pat.
Speaker 1: You do promise with resolvers, and it deconstructs the promise
Speaker 1: so that you just have references to the promise resolve
Speaker 1: and reject as as functions or objects.
Speaker 2: And then and then you can yeah, and then you.
Speaker 3: Can promise as an object and resolve and reject right.
Speaker 1: And so so then what I can do is I
Speaker 1: can I can basically reference those wherever I need. So
Speaker 1: if I have something else that needs to resolve or
Speaker 1: reject the promise, it just.
Speaker 3: It just called it can just called resolve or reject
Speaker 3: right directly.
Speaker 1: Yeah, it can just do it without having to write,
Speaker 1: without having to do work some magic on the promise
Speaker 1: object to you know, get it the internals or something.
Speaker 3: Like that exactly. So it's a it's a convenience method.
Speaker 3: You can definitely write the code yourself, but it was
Speaker 3: just really ugly boilerplate code. I've seen it done lots
Speaker 3: of code bases that that I've looked at, and it's
Speaker 3: nice to have a cleaner alternative, but you should have
Speaker 3: a good reason to use it rather than use it
Speaker 3: regular function promise semantics.
Speaker 1: Yeah, it's funny because you were talking about people having
Speaker 1: implemented it, and on the TC thirty nine proposal, it's
Speaker 1: like existing implementations and it shows where reacted it and
Speaker 1: view did it, and Axios did.
Speaker 2: It, and Typescript did it.
Speaker 3: Exactly exactly, and so now it's built in and there's
Speaker 3: no reason for any of them to actually do it themselves.
Speaker 2: Yeah, makes sense.
Speaker 3: Okay, now we're kind of done with things that have
Speaker 3: already actually in the language. Let's look at things that
Speaker 3: are not yet officially part of any standard.
Speaker 2: But are they are Stage four.
Speaker 3: Which means that they are effectively part of the standard,
Speaker 3: just that the standard, the relevant standard has not been
Speaker 3: released yet. Now, funnily enough.
Speaker 2: Hang on, so what does that mean?
Speaker 1: It means that the they've adopted the proposal, but they
Speaker 1: haven't rewritten the ACMASCRIPT standard to include them yet.
Speaker 3: Exactly. They release the standard once a year, so they'll
Speaker 3: release yes, twenty twenty five, sometimes later this year. But
Speaker 3: these things are kind of waiting for that document to
Speaker 3: be released.
Speaker 2: I gotcha.
Speaker 1: So people might be furiously working away at them now
Speaker 1: because they know now.
Speaker 3: They're actually all of them. Are actually the ones that
Speaker 3: I'm going to mention are actually implemented in browsers. Oh okay,
Speaker 3: but but they're not because from the browsers manufacturer's perspective,
Speaker 3: they've they've arrived, right, So why wait for the document
Speaker 3: if we know that they are going to be part
Speaker 3: of the document?
Speaker 2: Makes sense extra to the browsers.
Speaker 3: Yes. Indeed, the funny thing is that I've actually mentioned
Speaker 3: them in that episode five ninety a year and a
Speaker 3: half ago. Only then they were stage three, so it
Speaker 3: took them a year and a half to progress the
Speaker 3: stage four.
Speaker 2: Yeah, so again I like that they're being deliberate about it, So.
Speaker 3: Yeah, for sure. So the first one are set methods.
Speaker 3: Do you know the set object type in JavaScript? Have
Speaker 3: you used it? No? Set is kind of like the set.
Speaker 3: In math, it's basically a collection type. Oh yes, where
Speaker 3: something can either be part of the set or not
Speaker 3: part of the set.
Speaker 1: I thought you were talking about like a method on
Speaker 1: object or something called set object type.
Speaker 2: But no, the set, yeah, I've.
Speaker 3: Yeah, you do new set exactly, new set. You pass
Speaker 3: in an area of stuff to the constructor, and then
Speaker 3: those things are in the set. You can check whether
Speaker 3: something is in the set or not. You can add
Speaker 3: more stuff to the set or remove it from the set,
Speaker 3: but it's basically just to check if something is a
Speaker 3: part of a collection or not, and they and the
Speaker 3: thing is. As I alluded, set is really similar to
Speaker 3: set in math. And there are a whole bunch of
Speaker 3: operators that you can apply on sets in math, and
Speaker 3: it makes sense to have them on sets in JavaScript
Speaker 3: as well. So you've got, for example, union, which can
Speaker 3: take two sets and return a new set, which is
Speaker 3: then union of those two sets, so that it contains
Speaker 3: all the items that are in each one of them.
Speaker 3: Now it's an union rather than a concatenation because everything
Speaker 3: is in a set either either zero or one time. Right,
Speaker 3: So if it's a set of one two and another
Speaker 3: set of two three, and you do a union, you
Speaker 3: get a set with one two free right. Likewise, you've
Speaker 3: got dot intersection which can create an intersection of two sets,
Speaker 3: or dot difference which returns the difference between two sets.
Speaker 3: And uh, and these whole bunch of methods that have
Speaker 3: been introduced to sets and just makes working with sets,
Speaker 3: like working with mathematical sets, much cleaner and easier. I
Speaker 3: assume that they were there was probably more than one
Speaker 3: package package on NPM that implemented all this functionality. It's
Speaker 3: pretty straightforward to implement, but now it's built in, so
Speaker 3: you don't need those NPM packages anymore.
Speaker 2: Yeah.
Speaker 1: Yeah, And it makes a lot of sense because typically
Speaker 1: when you're using because because other collection types, you know,
Speaker 1: dictionaries or arrays, you're you're.
Speaker 2: Usually using those to hold all your data.
Speaker 1: And like you said, I like the way you put
Speaker 1: it where it's a mathema like the mathematical set. So
Speaker 1: this is you typical use sets for certain types of operations,
Speaker 1: and so if you need a friendly and easy way
Speaker 1: to do those kinds of operations, you can use sets exactly.
Speaker 3: That's what sets are for. So it's really nice to
Speaker 3: have those methods now built into the jobscript programming language.
Speaker 3: It's not like this big revolution. It's not like errow
Speaker 3: functions or like letter cons but it just makes JavaScript
Speaker 3: a nicer language out of the box.
Speaker 2: Yeah, so sets are a new edition.
Speaker 3: They didn't well, sets have been here for a long time.
Speaker 3: Sets were introduced with maps, I think way back in
Speaker 3: ES what's called ES six or EES twenty fifteen, so
Speaker 3: they've been here for like a decade. But it's nice
Speaker 3: to have these operations on sets now part of the standard. Okay,
Speaker 3: as I said, previously, you had sets, but if you
Speaker 3: wanted to do these an operation like union, you would
Speaker 3: have kind of needed to implement it yourself, and it
Speaker 3: wasn't difficult. You could spread the set into an array,
Speaker 3: then cancat into the two arrays and create a new
Speaker 3: set out of them, and you would get the union,
Speaker 3: but a whole bunch of copying going on. So now
Speaker 3: you've got a cleaner, more efficient implementation and certainly an
Speaker 3: alternative to bringing in yet another NPM package. Right. The
Speaker 3: other thing that was Stage three and now is released
Speaker 3: and it's a bit more difficult to explain are sync
Speaker 3: iterator helpers. So we've had episodes in the past, way
Speaker 3: back in twenty twenty one where I actually gave I
Speaker 3: talked for two whole episodes about iterators and why I
Speaker 3: think they're great, and I think I might have been
Speaker 3: able to convince AJ for the duration of the episode,
Speaker 3: and then he immediately chan is mine once then episode
Speaker 3: was over. Those were episodes for six eight and four
Speaker 3: six nine. For those who are interested in the details
Speaker 3: of what iterators are and how they work, I won't
Speaker 3: go into too much detail. Basically, it means that we
Speaker 3: now have methods like dot map, map or dot filter
Speaker 3: or dot reduce on iterators like we have them on
Speaker 3: let's say arrays, And the easiest way to explain how
Speaker 3: to use them is think of let's say I have
Speaker 3: an array of stuff, and I would do array dot
Speaker 3: let's say map, and then dot filter and then dot
Speaker 3: reduce or something like that. Now I can wrap the
Speaker 3: array itself in something that in something it's iterator dot from.
Speaker 3: So I do iterator with a capital I dot from
Speaker 3: on the array, and then on the return value from that,
Speaker 3: I do the dot map, dot filter, dot reduced, et cetera.
Speaker 3: Now you might ask yourself why would I do that
Speaker 3: and what's the difference. So, first of all, if it
Speaker 3: turns an iterator rather than an array. So if I
Speaker 3: then want to actually get an array in results as
Speaker 3: a result, I need to actually spread it into the
Speaker 3: result into an array. So you say, hey, this is
Speaker 3: actually even more work. I needed to do add an
Speaker 3: iterator from on the original array and then spread the
Speaker 3: result into an array. And you know what's the upside
Speaker 3: of all this? Why would I want to do all
Speaker 3: this stuff? There are a couple of reasons. First of all,
Speaker 3: iterator dot from is not just for arrays. It's for
Speaker 3: anything that's iterable. So it means that if I now
Speaker 3: have a new collection type. So for example, maps or sets.
Speaker 3: In JavaScript, there are collections they actually implement the four each,
Speaker 3: but they don't implement the filter, they don't implement a find,
Speaker 3: they don't implement a reduce, they don't implement filter. So
Speaker 3: how do I How do I invoke those methods on
Speaker 3: those types of collections. What I would usually see people
Speaker 3: doing is either avoid using these collections if they needed
Speaker 3: these methods, or alternatively copy them into arrays. And if
Speaker 3: you're going to copy them into arrays, then you might
Speaker 3: as well have just used arrays. So now I can
Speaker 3: apply iterator from to anything that supports iterators, any collection
Speaker 3: type that supports iterators, and then I can use all
Speaker 3: these methods on that collection. So that's advantage number one.
Speaker 3: I don't need to implement those methods directly on each
Speaker 3: and every collection type. I just need to implement iterators
Speaker 3: in the collection, and then I can use these methods
Speaker 3: on any collection type, be it a built in collection
Speaker 3: or one that I implement myself. Okay, so that's advantage
Speaker 3: number one. Okay. The second advantage is that it avoids
Speaker 3: all the intermediate arrays. When you do a dot map
Speaker 3: on an array, you get as a result or an
Speaker 3: array of the of the map. So when you do
Speaker 3: dot map, dot filter, dot whatever, you're getting a whole
Speaker 3: bunch of intermediate arrays that you're copying stuff from one
Speaker 3: to the next, to the next to the next and
Speaker 3: so forth. With iterators, they don't create those intermediate arrays.
Speaker 3: They work by doing lazy evaluation. You just get the
Speaker 3: results that you need, only the computations that are required
Speaker 3: without all the intermediate arrays. So they're actually they can
Speaker 3: actually be a lot more efficient in cases where you
Speaker 3: don't need all the values, right, And I'm really happy
Speaker 3: that they're here because iterators have been kind of a
Speaker 3: dud feature in JavaScript because they lacked all these helper functions. Hopefully,
Speaker 3: now maybe they'll they'll get some more love from the
Speaker 3: JavaScript developing the developer community. Time will tell. Maybe it's
Speaker 3: too late. I don't know, we'll see.
Speaker 2: Yeah, So these are the aerator helpers, right, No.
Speaker 3: These are the sync iterator helpers, the serator. The sync
Speaker 3: iterator helpers are here. They exist in browsers. You can
Speaker 3: already do iterator from inside Chrome, inside the Safari, inside Firefox.
Speaker 3: But what we don't have yet are a sync iterator helpers.
Speaker 3: They're stuck in stage two.
Speaker 2: I think yes they are. This one says, so.
Speaker 3: Yeah, the sync ones are stage four. The async ones
Speaker 3: are stuck in stage two. They've been stuck there for
Speaker 3: a whole while. That's really unfortunate. Again, what's the difference between? Yeah?
Speaker 3: And If our listeners are interested in the difference between
Speaker 3: sync inperators and a sync iterators, they should listen to
Speaker 3: episode four sixty nine where I explained the difference in detail.
Speaker 3: The other thing that I wanted to mention, which is
Speaker 3: kind of here are JSON modules you can now import
Speaker 3: not only JavaScript, you can import json.
Speaker 2: I'm sorry say that again.
Speaker 3: You know the JavaScript import command well, you can now
Speaker 3: import not only JavaScript modules, you can import JSON files
Speaker 3: and the result of the import is the Jason object.
Speaker 2: Oh cool.
Speaker 3: You just need to tell the import that you're importing
Speaker 3: a Jason it you you basically tell it, you assert
Speaker 3: that this is the type of what you're importing. Is
Speaker 3: that is that kind of clear?
Speaker 2: Yep? I'm just trying to find an example on the internet,
Speaker 2: but that makes sense.
Speaker 3: You do you do import json from something dot json
Speaker 3: and then at the end of that instruction you add
Speaker 3: with open curly brackets type colon json close curly brackets. Okay,
Speaker 3: Theoretically in the future we might have other types I
Speaker 3: don't know, maybe will import CSS or text files or
Speaker 3: I don't know what. But for now, we've got it
Speaker 3: for json. Now why is this useful? Because I mean,
Speaker 3: you could just do a fetch and then do a
Speaker 3: JSON parts. Why do we need to import? To be honest,
Speaker 3: it's more of a convenience than a necessity. But the
Speaker 3: convenience is that in a lot of cases we use
Speaker 3: JSON as configuration, and it's really useful to be able
Speaker 3: to directly import such configurations into the code. Yeah, think
Speaker 3: about I don't know, a wet back configuration or something
Speaker 3: like that. So you're creating some sort of node based utility,
Speaker 3: and that utility uses some sort of Jason configuration and
Speaker 3: now you can just import that configuration at the top
Speaker 3: of your file and then just use that configuration because
Speaker 3: if that configuration is missing, there's really nothing that you
Speaker 3: can do. And it also works with dynamic imports by
Speaker 3: the way.
Speaker 2: Oh nice.
Speaker 3: So yeah, it's it's again, it's not earth shaking, but
Speaker 3: it's really useful, I think, and it's nice to have
Speaker 3: it built into the language.
Speaker 2: Yeah.
Speaker 3: Well it's stage four, so that means that it's here.
Speaker 2: Yeah.
Speaker 1: The way I think about it is you import all
Speaker 1: the things that are required to run your application, and yeah,
Speaker 1: typically that's going to be other JavaScript files. But yeah,
Speaker 1: it makes sense right that you may have some set
Speaker 1: up data or whatever that you need in order for
Speaker 1: it to work, and so it's another requirement.
Speaker 3: It's just not code exactly. It's a declarative way to
Speaker 3: load your configuration data into your code basically, and you
Speaker 3: can be certain that if that configuration fails to load,
Speaker 3: then your code fails to load. And if it's successfully loads,
Speaker 3: than your code then gets to run with that configuration.
Speaker 3: It kind of blocks on that configuration. It doesn't proceed
Speaker 3: until that configuration is loaded. So it's not like I'm
Speaker 3: loading some configuration asynchronously I need to wait for it
Speaker 3: or write code that waits for it or something like that.
Speaker 3: I can just import it and use and rely on
Speaker 3: the fact that if I load it successfully, it means
Speaker 3: that I have this configuration data.
Speaker 2: Yep. Also for the iterator conversation, I did post episode
Speaker 2: for sixty nine just so that people can go reference
Speaker 2: that if they want.
Speaker 3: Yeah, basically they probably want to listen to both for
Speaker 3: sixty eight and for sixty nine together. To be honest,
Speaker 3: since we're running short on time, I want to mention
Speaker 3: just one Stage three standout. It's being stage streets means
Speaker 3: it's not yet here, so don't go try to use it.
Speaker 3: But there are various existing ways for you to actually
Speaker 3: test implementation, either NPM modules that implement it, or you know,
Speaker 3: Babel plug ins or some suff something like that. It's
Speaker 3: the temporal object or temporal namespace. Actually it's a more
Speaker 3: accurate way to put it. We all know that the
Speaker 3: JavaScript date object is pretty bad, uh it it has
Speaker 3: it has a lot of uh problems and limitations with it.
Speaker 2: I've done hand to hand combat with it before and
Speaker 2: I have lost some of those battles.
Speaker 3: Yeah, there are problems around working with the time zones
Speaker 3: with it. It only really supports your own your own time
Speaker 3: zone and doing all sorts of daylight saving time computation
Speaker 3: is really challenging and it and it's mutable with which
Speaker 3: makes it really problematics. It was created back in nineteen
Speaker 3: ninety five based on the Java the then Java date object.
Speaker 3: Java actually fixed their date object, but in JavaScript you
Speaker 3: couldn't for backward compatibility reasons, so we are stuck with it.
Speaker 3: So Temporal aims to fix these problems by providing an
Speaker 3: alternative to date, so date will still be there because
Speaker 3: obviously you can't take something away, but now instead you
Speaker 3: can use temporal. And by using Temporal you'll avoid the
Speaker 3: need for stuff like moment jas and other NPM modules
Speaker 3: which aim to fix a lot of the time problems
Speaker 3: that we face when we need to deal with date
Speaker 3: and time in JavaScript. Other things, it supports non Gregorian
Speaker 3: calendars for people who care about these things, for example
Speaker 3: the Hebrew calendar. You've got a more date format, parsing
Speaker 3: of options, so on and so forth. Just as a
Speaker 3: whole bunch of functionality for dealing with date and time
Speaker 3: in JavaScript. Now, as I said, unfortunately it's still stuck
Speaker 3: in stage three. I guess it's really complicated to get
Speaker 3: everything right in such a complex, complex domain. So they're
Speaker 3: taking their time. Hopefully we'll get it eventually.
Speaker 1: Yeah, I was gonna say, I as fraught as time
Speaker 1: and time zone and all of that stuff gets.
Speaker 2: And it's not just JavaScript.
Speaker 1: I know that that we have some listeners that are
Speaker 1: kind of polyglot folks, so they work on the back
Speaker 1: end and Ruby or Rust or go or something right,
Speaker 1: and so you folks know that, hey, some of this
Speaker 1: stuff is maybe easier in that language, but it's still
Speaker 1: hard sometimes. And then the folks that only do JavaScript
Speaker 1: like this is it's a hard problem. And so yeah,
Speaker 1: I understand why. Yeah, they may be working through some
Speaker 1: of the finer details to make sure that they get
Speaker 1: it right, because, yeah, if they put in an implementation
Speaker 1: that really does kind of just shine. I mean, that's
Speaker 1: a big area of pain that a lot of people
Speaker 1: have to deal with. Now, you said at stage three,
Speaker 1: so is it implemented or somewhat implemented or partially implemented
Speaker 1: in browsers.
Speaker 3: No, it's not really implemented in browsers as far as
Speaker 3: I can tell.
Speaker 1: Okay, they do have some polyphills that are listed in
Speaker 1: the proposal.
Speaker 3: Oh yeah, for sure. It's it's an object in JavaScript,
Speaker 3: it's a name space in JavaScript, so you can definitely
Speaker 3: poly fill it. But you know some of these polyfils.
Speaker 3: First of all, I haven't checked how complete these polyfields are.
Speaker 3: And uh.
Speaker 2: Yeah, the REA says so it was updated. Oh that's helpful.
Speaker 2: It says it was updated last year, very very helpful.
Speaker 1: It does list other changes two months and four months ago,
Speaker 1: so it might be longer ago than that.
Speaker 2: But the two that it lists are at.
Speaker 1: JASS temporal slash polyphil, which I'm assuming is an NPM package,
Speaker 1: and that says that the alpha release is available. And
Speaker 1: then temporal dash polyphil, which is a full calendar implementation
Speaker 1: is it says the beta release is available.
Speaker 3: So.
Speaker 2: It might be worth looking at.
Speaker 1: But yeah, it doesn't look like any of these are
Speaker 1: entirely stable.
Speaker 3: Now we've effectively run out of time. I was going
Speaker 3: to talk about two more. One is the explicit resource
Speaker 3: management with the using keyword. It's this one actually does
Speaker 3: modify JavaScript semantics. I did actually discuss it way back
Speaker 3: in episode five and ninety a year and a half ago.
Speaker 3: It was then it's still stage three now, so uh.
Speaker 3: The one interesting thing is that Typescript actually added it
Speaker 3: in version five point two about a year and a
Speaker 3: half ago, So it seems that typescip kind of jumped
Speaker 3: the gun on that one. They saw it in stage three,
Speaker 3: they assumed it was going to be released soon, and
Speaker 3: so they added support for it, and but it's not
Speaker 3: here yet. So it exists in typescript but not in JavaScript,
Speaker 3: which is amusing.
Speaker 2: Yeah, I just episode as well.
Speaker 3: Yeah, and the other one is something with this really
Speaker 3: cool name called Shadow Realm. I guess we'll need to
Speaker 3: find a different episode to talk about that one. It's
Speaker 3: that one is currently in stage two point seven, which
Speaker 3: means it's not even stage three, but it sounds good. Yeah.
Speaker 3: You know, one of the things that I've been thinking about,
Speaker 3: and maybe if we get requests from our audience to
Speaker 3: do it, is to do another episode about JavaScript features
Speaker 3: stuck in Purgatory. There are a whole bunch of really yeah,
Speaker 3: there are a whole bunch of really interesting JavaScript features
Speaker 3: that have been staged two for like what feels like forever.
Speaker 3: I wonder if it's worthwhile to actually even talk about them,
Speaker 3: because on the one hand, some of them are really
Speaker 3: cool and really interesting and they add a lot of
Speaker 3: really interesting twists to the JavaScript language. But on the
Speaker 3: other hand, it seems like they're just they're just stuck there.
Speaker 3: So the committee is not really doing away with them,
Speaker 3: but they're also not progressing them. They're so they're kind
Speaker 3: of stuck. I wonder if it's worthwhile to even talk
Speaker 3: about them. What do you think?
Speaker 1: I think that would definitely be interesting. It's also interesting
Speaker 1: sometimes the how do I put it, There are things
Speaker 1: that kind of float.
Speaker 2: Out there for a while.
Speaker 1: I'll go back to the legislative example, right because I mentioned,
Speaker 1: you know, laws passing and bills passing and stuff. There
Speaker 1: are things that get proposed like every year that just
Speaker 1: never quite get enough traction. And sometimes what's needed is
Speaker 1: somebody just points it out and then all of a sudden,
Speaker 1: some energy comes up behind it and things move, And
Speaker 1: so I'm imagining that, you know, I don't know that
Speaker 1: we have that bit that kind of influence necessarily, but
Speaker 1: it could start the process so that other folks start
Speaker 1: talking about it too. And we get some exposure as
Speaker 1: far as oh, this really is a good idea, and
Speaker 1: we ought to just go and finish it, right, whether
Speaker 1: that's maybe we modify it to solve some of the concerns,
Speaker 1: or you know, there's a little bit more work put
Speaker 1: into just you know, putting the polish on it or whatever,
Speaker 1: and then we get another cool thing in JavaScript.
Speaker 3: Yeah, and I would imagine that AJ would be really
Speaker 3: happy that they're not here yet, not to hear maybe forever.
Speaker 1: Yeah, well cool, Well, yeah, I mean all of this
Speaker 1: stuff's really really fascinating and I'm looking forward to hopefully
Speaker 1: seeing more and more people use some of these features.
Speaker 3: Yeah, all the features that we spoke about today are
Speaker 3: effectively in the language, so there's absolutely no reason not
Speaker 3: to use them. And in fact, as I explained, in
Speaker 3: some cases it's preferably preferable to use them rather than
Speaker 3: the alternatives. So as an example, again, instead of dot reverse,
Speaker 3: use two reversed. That's like a prime example of something
Speaker 3: that we should use. Or another one, if you're doing
Speaker 3: all sorts of mathematical operations with unions, then maybe instead
Speaker 3: of using some NPM package, you just use what's now
Speaker 3: built into the JavaScript language itself.
Speaker 2: Yeah, so I did a search on Shadow Realm, and
Speaker 2: it looks like.
Speaker 1: There's a Twilight something Twilight I think it's D and
Speaker 1: D book that's called Shadow Realm.
Speaker 2: And then there were.
Speaker 1: Like eighteen of the front page links were you gi
Speaker 1: oh okay card game?
Speaker 3: So in other way, it must be a cool Java's
Speaker 3: good feature if it's called shadow Realm. I mean, right,
Speaker 3: the name is really cool.
Speaker 1: Yeah, So anyway, but yeah, I'd love to dive into
Speaker 1: some of these features. Yeah, some of the ones that
Speaker 1: are in limbo or purgatory or whatever you want to
Speaker 1: call it. And yeah, but it's also good to just
Speaker 1: see some of this stuff come along. And like you said,
Speaker 1: none of these are huge changes, but some of these
Speaker 1: sure seem like they'd make my coding either more stable
Speaker 1: or easier to do, and so.
Speaker 2: I'm all about that. So all right, well, let's go
Speaker 2: ahead and do our picks. Do you want to do
Speaker 2: picks first or do you want me to go first?
Speaker 3: I can go first. So first of all, people are
Speaker 3: listening my I've noticed that I've got a bit of
Speaker 3: a head cold and the stuff he knows, hopefully that
Speaker 3: goes away. So my first pick would be for my
Speaker 3: head cault to go away. Yeah, it's not really such
Speaker 3: a huge bother, just annoying, So that would be my
Speaker 3: first pick. My second pick is, we actually had a
Speaker 3: fun day to day at work. We are the team
Speaker 3: that I'm mostly working with. We went out together to
Speaker 3: do to play laser Tag, which was a whole was
Speaker 3: a lot of fun. So my second pick would be
Speaker 3: to have fun days as team building exercises. And the
Speaker 3: third pick would be to do it a laser tag
Speaker 3: game because it's just fun. And those would be my
Speaker 3: picks for today. Short and sweet.
Speaker 2: Yeah, laser Tag is fun. I'm gonna pick it's it's
Speaker 2: a second version of a board game I've picked in
Speaker 2: the past, so I've picked Machi Koro in the past,
Speaker 2: and essentially, just to give you an overview of Machi Korro, essentially,
Speaker 2: your building a town.
Speaker 1: You buy buildings, and then you roll dice and you
Speaker 1: get money based on whether it's somebody else's team or
Speaker 1: your team, and whether you have a card with that
Speaker 1: number on it, and then you buy landmarks and once
Speaker 1: you've built all four landmarks, you win. That's Machi Korro.
Speaker 1: Machi Koro two is a little bit different, so instead
Speaker 1: of building four landmarks, you only have to build three.
Speaker 1: But the other thing is is that in Machi Koro
Speaker 1: you put out all the different types of buildings you
Speaker 1: can build in your town. In Machi Koro two, what
Speaker 1: you do is you have decks of cards that have
Speaker 1: numbers one through six, decks of cards that have numbers
Speaker 1: seven through twelve, and then you have landmarks.
Speaker 2: And so you flip cards over until you.
Speaker 1: Have basically five unique buildings in each row, and then
Speaker 1: you win when you build three landmarks. And so you
Speaker 1: play the rest of the game plays the same. You
Speaker 1: roll the dice, if you have the building, you get
Speaker 1: paid the landmarks in Machi Korro, the original have fixed
Speaker 1: pricing for each landmark.
Speaker 2: In Machi Korro too. Your first landmark has a cost,
Speaker 2: your second landmark has a cost, and your third landmark
Speaker 2: has a cost, and those costs are on the card.
Speaker 1: I mean, those are the only differences. The rest of
Speaker 1: the game plays the same. It does give you a
Speaker 1: little bit more variety, and it makes the strategy just
Speaker 1: slightly a little bit more. You really have to think
Speaker 1: about it a little extra in order to get what
Speaker 1: you want, because the cards do give you different abilities,
Speaker 1: but it's not such a wide breadth of abilities that
Speaker 1: you're going, oh.
Speaker 2: Man, I don't know how to figure this game out.
Speaker 2: So we played it with some friends of ours. We
Speaker 2: got it for Christmas, my family did.
Speaker 1: And it's board game geek has a weight of one
Speaker 1: point four to eight, so it's still a pretty simple game.
Speaker 1: I think Machi Koro's like one point three. So yeah,
Speaker 1: very very approachable. Simple game. Says age ten plus can
Speaker 1: play it.
Speaker 2: My daughter's nine.
Speaker 1: I think she'd be fine playing this game. It says
Speaker 1: playtimes forty five minutes. I'm not sure if I remember
Speaker 1: how long it took us. Probably about that long.
Speaker 2: So anyway, it's a fun game if you're looking for
Speaker 2: just something short, not terribly complicated that you can play
Speaker 2: and kind of chat over the table while you play it.
Speaker 3: Chuck, I'm kind of curious, since you are such a
Speaker 3: board game geek slash expert, if you had to name
Speaker 3: your like top board game, or at least one of
Speaker 3: your top board games, just out of curiosity, what would
Speaker 3: that be? One in the top three or top five? Please?
Speaker 2: So that's a little bit tricky, just because there's so
Speaker 2: many kinds of board games.
Speaker 3: Yeah, but there must be something you really like.
Speaker 1: So the ones that I've been playing a bunch lately
Speaker 1: and I can, I can give you a couple of them.
Speaker 2: I've already picked them on the show.
Speaker 3: I'm just curious which one you like the most.
Speaker 2: I'd really have to think about that.
Speaker 1: Like I said, the ones that we've been playing lately
Speaker 1: that we're really liking our Mysterium. We got expansion for that.
Speaker 1: It doesn't change the gameplay at all. It's just more cards.
Speaker 1: We got two expansions.
Speaker 2: The other one that we've been playing lately is Betrayal
Speaker 2: at House on the Hill. I should put links to
Speaker 2: these in here. And that one's a fun one.
Speaker 1: It's it's relatively fast too, but it's more of a
Speaker 1: role play game almost. The idea is you have you're
Speaker 1: a group of people that come into a haunted house,
Speaker 1: and you explore the house, and eventually a haunting happens,
Speaker 1: and then you're trying to complete goals. One of you
Speaker 1: frequently becomes the trader, almost always, not always, but almost always,
Speaker 1: one of you becomes the trader, and then everybody's playing
Speaker 1: against that other player. And the thing that's fun about
Speaker 1: it is that the scenario you wind up playing changes
Speaker 1: from game to game, and so it's and the as
Speaker 1: you explore a room, you place tiles for the rooms,
Speaker 1: and so your map changes every game too, and so
Speaker 1: there's a lot to like about that. Honestly, sometimes I
Speaker 1: really really like the kind of the thinker games. I'm
Speaker 1: not so some of the big big ones that people
Speaker 1: tend to like that I'm not a fan of, or
Speaker 1: like Seven Wonders, or there are some.
Speaker 2: Of them where you're almost playing your own game and
Speaker 2: then at the end you see who played it the best.
Speaker 1: But you do interact with each other as far as
Speaker 1: did I do better at you with this than that?
Speaker 1: But then you've got other games.
Speaker 2: I'm trying to think.
Speaker 1: We've been playing Risk Legacy, which I like but I
Speaker 1: don't love. With my friends, we played Heat, and I.
Speaker 3: Think with Risk is that play properly it can take
Speaker 3: such a long time.
Speaker 2: Yeah, And we're getting to the stage with Risk Legacy.
Speaker 2: So Risk Legacy modifies the board every time and has
Speaker 2: special rules for how you win, and so it doesn't
Speaker 2: take as long.
Speaker 1: But the last time we played it, it's starting to
Speaker 1: get to the point where you really almost have to
Speaker 1: do world domination to win the round.
Speaker 2: And so it does take quite a bit longer. Yeah,
Speaker 2: I tend to like Settlers of Catan.
Speaker 1: That was one of the games that I kind of
Speaker 1: got into gaming board gaming on. But anymore, it's like
Speaker 1: there are so many games that just have better mechanisms
Speaker 1: in them.
Speaker 3: And so, yeah, if if somebody likes Catan and wants
Speaker 3: a better alternative, what would you recommend? Uh, well, you
Speaker 3: need to think about.
Speaker 2: It, Yeah I do. Uh let me let me. I'll
Speaker 2: I'll come next time with my top two or three.
Speaker 3: Games that your homework for next time.
Speaker 2: Yeah, but I will tell you that.
Speaker 1: Yeah, for the social games, we're really liking Mysterium. If
Speaker 1: you want a lighter social game, things like Sushi Go
Speaker 1: Party are fun if you're if you're looking at like
Speaker 1: maps and things like that. I mean, there are games
Speaker 1: out there. I kind of have this nostalgic feel for
Speaker 1: Access and Allies. But that's another one.
Speaker 2: That takes like three or four hours to play.
Speaker 1: Yeah, there are a bunch of good ones out there.
Speaker 1: Let me think about that and I'll come back to it.
Speaker 3: But to be honest, I don't see myself playing a
Speaker 3: board game for six hours.
Speaker 2: Yeah. The ones that I like, they take you about
Speaker 2: an hour and a half, and.
Speaker 1: You have some idea about where you're at as far
Speaker 1: as like am I winning or not, but you don't
Speaker 1: entirely know because there's always some twist that you know,
Speaker 1: and so somebody could be building towards something and you
Speaker 1: don't really see it until they resolve it and then
Speaker 1: you go oh wow, right, but then you turn around
Speaker 1: and you resolve your thing on the next turn, and
Speaker 1: then everybody goes, oh, now he's you know. So those
Speaker 1: are the kinds that I like, and the ones where
Speaker 1: I have enough room to get creative on the strategy right,
Speaker 1: where there's not just kind of a tried and true
Speaker 1: if you do this every time you're going to win,
Speaker 1: they go yeah, go is a good example of that
Speaker 1: with fairly simple rules. So anyway, other picks, My wife
Speaker 1: and I started watching prison Break, which is an older
Speaker 1: TV show.
Speaker 3: On Oh yeah, that's on the nineties.
Speaker 1: I think I think it's early two thousand's but still. Yeah,
Speaker 1: I've been liking that. I'm still watching. I have the
Speaker 1: last season of what's it called Reacher, No, not Reacher
Speaker 1: Jack Ryan. I've been watching that.
Speaker 3: Yeah, I tried to watch it. I couldn't really get
Speaker 3: into it. I actually read some of the what's his
Speaker 3: name Clancy I think, Uh, yeah, I read some of
Speaker 3: the books. Yeah, I read some of the Tom Clancy books.
Speaker 3: I could never actually get into either the movies or
Speaker 3: the TV shows. I don't know.
Speaker 1: Yeah, there are older movies to hunt for. Red October
Speaker 1: is a terrific book.
Speaker 3: Yeah, that's his best one, I think.
Speaker 1: Yeah, I've read a few others of his books. But
Speaker 1: the TV show is not based on any.
Speaker 2: Of the books. Oh yeah, they just pulled some of
Speaker 2: the characters out and they basically have a new threat
Speaker 2: every season. That said, it's not the best ever kind
Speaker 2: of action spy TV show that I've ever seen, but
Speaker 2: I'm enjoying it.
Speaker 3: If you've got Peacock, I would I actually picked it
Speaker 3: a while back, but it might be nice for you
Speaker 3: to watch. If you've got Peacock. I don't know who
Speaker 3: has Peacock, but I do. Then it's a Day of
Speaker 3: the Jackal.
Speaker 1: Yeah, you recommended that a few weeks ago, and that's
Speaker 1: kind of on my list. But yeah, anyway, so I've
Speaker 1: been watching that. I'm in the middle right now, and
Speaker 1: I'm gonna pick these books again. I'm on book like
Speaker 1: nine or ten of the sort of truth books, and
Speaker 1: they they are so good. I've gotten so I read
Speaker 1: them in high school and then I hadn't really touched
Speaker 1: them again, and so he put out more books. The
Speaker 1: author had passed away a few years ago, but he
Speaker 1: wrote like very good.
Speaker 3: Yeah, I recall reading some of his stuff. I'm trying
Speaker 3: to remember what.
Speaker 2: Yeah, those were his big series, but yeah, I.
Speaker 3: Yeah, see he died five years ago.
Speaker 1: But anyway, he's I've just been really really enjoying these books,
Speaker 1: and so yeah, I'll pick those as well. I don't know,
Speaker 1: I'm kind of rambling at this point because you derailed
Speaker 1: me with the question about board games.
Speaker 2: But yeah, and then I'm.
Speaker 1: Just working on getting JavaScript Geniuses and the AI boot
Speaker 1: camp roll it out. So yeah, anyway, I guess we'll
Speaker 1: wrap it up because I am not going to keep
Speaker 1: rambling about this stuff.
Speaker 2: But yeah, until next time, pokes Max out