Steve:
Hello everybody, welcome to another exciting episode of JavaScript Jabber. I am Steve Edwards, the host with the face for radio and the voice for being a mine, but I'm still your host today with me. I have one other person, fellow panelists, Dan Shapir, ringing in from Tel Aviv, Israel. How you doing, Dan?
Dan:
I'm doing great. You know, the weather is wonderful, a bit on the warm side, but you know, can't complain.
Steve:
Right, but the politicians are still awful, right? If I remember
Dan:
Oh
Steve:
that
Dan:
yeah,
Steve:
correctly.
Dan:
and they're only getting worse. I don't know, you know, sometimes it's difficult to tell if like, all I can say is that their incompetence is getting in the way of their scoludgery, or however you pronounce it, scoludgery,
Steve:
Skullduggery?
Dan:
that's it.
Steve:
Yes.
Dan:
Yeah, that's the way you pronounce it. So yeah, that's the best thing I can say about them.
Steve:
Yes, the same is true here. So you're not alone in that. So Chuck is running around Disneyland as we speak. And for some reason, he made that a higher priority. I don't get it, but it is
Dan:
Ha!
Steve:
what it is.
Dan:
Yeah, it is what it is.
Steve:
And AJ is busy. So it's just Dan and I doing another intercontinental podcast episode. So
Dan:
Mm-hmm.
Steve:
today, Dan is going to be doing most of the talking, because we are talking about the Things coming down the pike from TC39. This is stuff that tried up his alley. So we've got one, two, three, four, five, six things, maybe more depending on how we address them
Dan:
Yeah.
Steve:
coming down from TC39. So with that, Dan, take it away.
Dan:
Yeah, you know, I like to keep abreast of what's going on with our favorite programming language, especially given that AJ is not here. So it is, we can say that it's our favorite. And you know, things are keep getting added to the language, you know, the rate seems to be slowing down. But you know, there are some really interesting additions happening. Now we had episodes about it in the past, most recently. we had an episode with, who was it?
Steve:
Thomas.
Dan:
Yeah, Thomas Randolph, episode 532, where we spoke about some, I don't know, 10, 20 proposals, something like that. And it was such a lengthy discussion, it actually became two-parter. But interestingly, the things that I recently noticed that are really... being added to the language kind of as we speak are things that we didn't even discuss during that conversation. So, you know, it's funny how, you know, we kind of missed it. Either the committee did some end run or something, you know, or we just failed to notice it. But in any event, I think they're pretty interesting. And some of them, at least, are also pretty useful. So I thought that it was definitely worth a discussion. But before we actually dive into the details of those proposals, I want to briefly recap the process that TC39 uses to go through adding features into the language, because they don't just do it willy-nilly. They have this whole process with multiple steps and stages. And And that's what I would like to run through. So yeah, so that's the first thing. So it turns out that TC39, in the process of adding stuff into the JavaScript programming language, actually has five steps, starting with step zero, because everything's supposed to be zero-based in JavaScript. Yeah. So stage zero. is basically when somebody approaches the committee and says more or less, I have a cool idea and here it is. So it's really a mechanism for allowing essentially almost anyone to propose additions or changes to the language. No, that's more or less it. Um, but to be an actual candidate into the language, you have to move to stage one where you need to make a concrete case for the addition of that feature. describe its structure, identify potential challenge with it, is with it, and probably the most importantly, you need to identify some champion who will advance this addition, you know, lead the task as it were. So that's stage one. Stage two is a stage in which the feature gets precisely described in terms of syntax and semantics, using a formal specification language. and the committee, things move to stage two when the committee expects that there's a good chance that they'll eventually actually make it into the language. It might take a while, it might even take a long while, but there's a good chance that it will be added to the ECMAScript language specification. And stage three indicates that effectively kind of will be added. The discussions have reached the stage where, you know, there's no more to discuss about it. It looks good. They want to add it. They do, they are looking for potentially further refinement, but one that stems from actually trying out that feature in the field. So that's stage three when you start seeing those features implemented in transpilers or maybe even. in JavaScript engines behind, let's say, a feature flag or something like that. And the final stage is stage four, which basically says that the feature is ready and it's just waiting for the next official version of the spec. So because there is a version released every year, you kind of need to wait for that document to come out, but it's actually already officially part of the language. So those are the five. stages of adding a feature into the ECMAScript
Steve:
So far, so
Dan:
language specifications so
Steve:
good.
Dan:
that
Steve:
So
Dan:
it
Steve:
let me ask
Dan:
does
Steve:
you this
Dan:
get
Steve:
question before
Dan:
added
Steve:
we get into
Dan:
into
Steve:
details.
Dan:
JavaScript.
Steve:
And this is one of the things I've always
Dan:
So far,
Steve:
wondered
Dan:
so good.
Steve:
because I'm not a real low-level programmer.
Dan:
Okay then.
Steve:
So ECMAScript, or the committee decides, OK, let's implement this. So now you've got the different browser engines. You've got the different manufacturers, Chrome, Firefox, Safari, and their underlying engines. So are the implementation details of how this is going to work? how it's implemented in each browser up to the browser manufacturers. I mean, it's basically, okay, here's what needs to happen. Make it happen. We don't care. It happens as long as the end result is the same across the board. Is that how that works?
Dan:
Yes, in that regard it's no different from let's say the DOM specification that comes from the W3C.
Steve:
Right.
Dan:
The engines are separate and distinct, they don't share code between them. So yeah, the implementation might be done in a completely different programming language for example. Certainly a different implementation, a different open source project. Yeah. But they do need to adhere to the standard. And all the engine builders or creators actually have members in the TC39 committee. So nothing really can get added into the language unless the engine makers all agree that it's can and should be added into the language. So if they don't know how to implement it or
Steve:
Okay.
Dan:
think that there's a problem in implementing
Steve:
Anyway, that was all my
Dan:
it,
Steve:
question. Just a little
Dan:
it
Steve:
clarification
Dan:
won't get added.
Steve:
on the underlying work once the committee says do it.
Dan:
Yeah, you know, some things are tricky. There's the kind of quote unquote infamous case of the tail recursion or tail optimization for recursion, you know, when you can call a recursive function kind of infinitely without exploding the stack, which turned out to be actually, so it kind of got added into the language and then it turned out that it was actually tricky. for some of the engine builders to actually properly incorporate it into the engines. And it turns out that as a result, it mostly hasn't been. So these things can theoretically happen, but they really strive to avoid them. So I'm actually going to go through the proposals, starting with several proposals in stage three. Then if we have time work our way into a few proposals in stage two and then me even maybe one that it's still in stage one Because obviously the more interesting ones are the ones that are you know? Effectively going to be a part of the language not ones that are kind of stuck in purgatory So yeah And and the funny thing is what kind of Drove me to propose this topic is that I saw two unrelated tweets about language features that are in stage three and that are actually being implemented. And looking at what they do and say, hey, I'm not familiar with these. So I actually started reading about them and try to figure out why they might be helpful, what I think about them. And that's kind of what I wanna talk about today. So the first proposal that I would like to mention, which as I said is in stage three, is called the using keyword for automatic resource disposal. And it has to do with objects that have a lifetime or a time span associated with them. Good example might be an object that encapsulates a database handle that you want to close when you no longer need that database connection, or maybe something that encapsulates web sockets that, again, you would like to close once you don't need that web socket anymore, or maybe a file handle. There are plenty of such examples. Now, you might think, why do we need to explicitly control object lifetime? I mean, don't we have the garbage collection for that? And doesn't the garbage collector automatically dispose of such resources? And the answer is that it does or it can. But the problem is with the garbage collector that you don't really have any control about when it runs. So it might be in a few seconds or theoretically could be in a few minutes or maybe even never. And as a result, it means that such resources might hang around a lot longer than you might want or might expect. Now, when resources are plentiful, like memory, then that's not a problem. But when resources are scarce, like database handles or like file handles or network handles, then you want to dispose of them as soon as you don't need them so that, you know, the system can reuse these resources for other tasks. Otherwise it might try to obtain a database handle and fail. So, yeah, so you really want to have kind of this guarantee, as it were, that as soon as you don't need that resource anymore, the system becomes aware of it and can reclaim it. Now, what usually happened in these kind of cases is that you would use something like try finally. So you put the part where you create the resource or claim the resource in a try block. And then you would have a finally block associated with it where you would call some sort of a dispose or release or close method on that object. Now, what that guarantees is that whichever which way you exit that try block, be it because of a return statement or an exception being thrown or whatever, the language guarantees that the finally block will execute and then you get that chance to explicitly release that object. But that can get kind of tricky because you're really putting the onus of properly releasing resources on the code, on the user, on the developer that's actually using that resource. If you're building a library that encapsulates database handles, what you really want is for the library itself to implement the mechanism to guarantee proper resource lifetime and not to be dependent. on the developer that's using the library, especially because it can get tricky to properly nest and order finally blocks.
Steve:
This is
Dan:
Have
Steve:
the first
Dan:
you
Steve:
I've ever
Dan:
actually
Steve:
heard of a finally
Dan:
used finally
Steve:
block
Dan:
blocks
Steve:
to be honest.
Dan:
in your code for that kind
Steve:
Tells
Dan:
of purpose?
Steve:
you how much of an in the weeds developer I am. I've used try catch, you know, I've seen it and maybe
Dan:
Ha
Steve:
used
Dan:
ha!
Steve:
it here in the.
Dan:
To be honest, unless again you're dealing with resources like database handles from within your JavaScript code, then you probably don't need to.
Steve:
Yeah,
Dan:
So
Steve:
I mean, that makes
Dan:
I'm,
Steve:
sense. We deal
Dan:
from
Steve:
with
Dan:
what
Steve:
the same
Dan:
I
Steve:
thing
Dan:
know, you
Steve:
in
Dan:
primarily
Steve:
PHP,
Dan:
use other programming
Steve:
you know,
Dan:
languages
Steve:
on the server
Dan:
on
Steve:
side
Dan:
the back
Steve:
where you've got
Dan:
end
Steve:
database
Dan:
for stuff
Steve:
connections,
Dan:
like that.
Steve:
you got to open them and close them. And, and how that gets handled. You know, in my case, it's usually been abstracted away by a Laravel or a Drupal or something like that. So, but when I was first writing PHP before those existed, then yeah, I can remember dealing with database connections, but they were usually server side, not a, not JavaScript side, client side.
Dan:
Well, yeah,
Steve:
Right.
Dan:
it has to do with the fact that the JavaScript is much more used on the server side these days. I mean, on the client
Steve:
Mm-hmm.
Dan:
side, lifetime usually is not a problem in any event so much because everything gets released or closed anyway when you close the tab or navigate away or whatever. So really the main issues with the long lived objects and long lived sessions and scarcity of resources usually has to do when you're running. JavaScript on the backend, which is much more likely than it ever has been. Now that
Steve:
with
Dan:
you know,
Steve:
node
Dan:
we've
Steve:
being
Dan:
got
Steve:
the
Dan:
all
Steve:
first,
Dan:
those
Steve:
the
Dan:
JavaScript
Steve:
primary one, yeah.
Dan:
frameworks, like claiming the backend, uh, as it were. Yeah, so we've got React server components and whatnot that, you know, are kind of trying to position themselves as the replacement to PHP in a lot of ways. So yeah, we're likely to be seeing much more code, JavaScript code or TypeScript code running in the backend and having to deal with these sorts of issues. Now the using keyword which is in was introduced for this purpose is actually derived from or influenced by constructs that exist in other programming languages. Like for example, I know that C sharp has this mechanism and also uses the same keyword for it. So they're definitely being influenced by other programming languages in this context. Now the way that this feature works sounds a bit complicated and hopefully I can explain it verbally, you know, without code demos, but it's actually Fairly straightforward, I think. So the idea is that if you've got an object that you want to have it do its own cleanup. So you have an object instance that encapsulates some functionality. Let's say it has the database handle in some internal field property. And you want it to close that. handle automatically when it's no longer needed. What you do is you specify a method on it, and that method needs to have a special name. And that special
Steve:
All right.
Dan:
name is symbol.dispose. We spoke about symbols in the past. Symbols are like these unique identifier values. that you can use instead of strings for property names. And they are kind of guaranteed to be unique. So you don't get conflicts with user land code. And there are a bunch of such global symbols that are defined in order to specify language level properties or methods that people can can put on their object. For example, iterators have also used this kind of thing to specify the, for getting the actual iterator out of an object. But anyway, so what you would do is you would do an open square brackets, symbol dot dispose, close square brackets, that would, and then colon and the method. uh definition and in that way you know you can if you put a proper an expression inside of a brackets in this in this way it can actually calculate the uh property name so in this case again the property name would be simple a symbol dot dispose and then when you want to use it what keyword. So you write using x equals the constructor of the object, the actual object, sorry. So you assign the object into a variable, but you declare the variable instead of using const or let, you use the using, the new using keyword. And what this guarantees is that is that when that variable goes out of scope, for example, basically at the end of the block or at the end of a function, then it guarantees to invoke that dispose method. So you got a mechanism in which you can guarantee that the cleanup code will execute when the variable goes out of scope, when it effectively dies. I'm hoping that I described it clearly. We will put a link to a short blog post about it that Matt Pocock wrote. And once you see it in the code, it's just like five lines of code. So it's really easy. So like I said, you just add a property with a specific name to your object. And when you assign that object into a variable, you declare the variable with the using keyword instead of const or less. That's all you really need to do in order to get this functionality. And because you don't need to mess about with all the try and finally and stuff like that, again, when the variable dies, then that cleanup method will be invoked. It's guaranteed. So that way, we can get guaranteed cleanup. Now, interestingly, uh, this is going to be part of TypeScript 5.2. It turns out that TypeScript, you know, they, they don't, they, or let's put it differently. Let's say it in a positive rather than the negative tense. Um, they, they only add things into TypeScript these days when they know that they're going to be part of JavaScript. And since things that are in stage three, are going to be part of JavaScript, you know, it might take a while, but they will be, they feel okay about adding them. So that's why they're okay with adding this feature into TypeScript 5.2, even though it's not yet supported by your browser. So I'm assuming that TypeScript will transpile this code for now into some sort of try finally thing. But eventually when JavaScript does support it, then they could just emit the JavaScript code that would look
Steve:
So far so good,
Dan:
like
Steve:
it's actually
Dan:
the TypeScript
Steve:
making sense.
Dan:
code just without the types. So far so good. They're also doing the ability to specify instead of dispose, they're also going to have an async dispose, which basically just waits on the dispose to finish before it proceeds going out of the block. So for example, if closing the database is a synchronous operation, but you... don't want to proceed with execution before it finishes because maybe you're worried that then you'll try to get a new handle and fail and you want to guarantee that the handle will be available, then you use a sync dispose instead of dispose and the method is asynchronous and it just works that way. So that's the first interesting feature that I wanted to bring up and again, It's interesting that when we spoke about the TC39 features that we liked, this one never even came up. I don't know how we missed it. Again, maybe it was just a flu through the process, and we just didn't notice it back then. So that's the first one. The next one that I wanted to talk about is actually one that's kind of near and dear to my heart in a lot of ways. And that's. iterator helpers. If you may recall Steve, I had an entire two episodes on iterators and generators in JavaScript and why I think they're great, but it's also undoubtedly true that they've kind of failed to a great extent because hardly anyone ever uses them explicitly. Generators make it really easy to create your own custom iterators, but very few people that I know of
Steve:
What's a
Dan:
actually
Steve:
use case for creating
Dan:
use it
Steve:
your
Dan:
or
Steve:
own
Dan:
even really understand
Steve:
custom
Dan:
how it works.
Steve:
iterator?
Dan:
Well, if you're creating some sort of collection or sequence, it's just a really nice way of encapsulating iteration. A lot of other programming languages, by the way, have their own iterator libraries and implementations. Java has it. C++ has it. A lot of programming languages have it. And for example, Dino actually uses it. So if you want to process streams of data, let's say data coming over a socket or a web socket or something like that, you can actually encapsulate it as an iterator or synchronous iterator in Dino, which makes it really nice because you can write your processing code as if it were a regular for each loop. of for all of action
Steve:
So
Dan:
loop.
Steve:
in other words, you can handle all, you can sort of,
Dan:
So it's really
Steve:
what's
Dan:
nice
Steve:
the term
Dan:
in that
Steve:
I'm looking
Dan:
regard.
Steve:
for, handle all
Dan:
And...
Steve:
the custom stuff behind the scene, but from a top level code, it looks like you're just iterating over something.
Dan:
Exactly, you just use let's say a for of or for a weight of it looks like a regular loop over an array or something But on underneath the scenes, it's actually potentially doing something much more sophisticated Like reading blocks off of the network or file system or whatever And and in that regard, it's really cool. It's really nice you can Theoretically create your own data structures if you want. For example, map and set in JavaScript actually support iterators. So instead of copying their content into arrays, you can iterate on top of them directly. But like I said, unfortunately, most people just don't do it. And if they use iterators, it's really behind the scenes for things like the spread operator. And they might not even be aware that it actually even uses iterators in order to implement it. They just, you know, use it and it works. Now, one of the reasons I think that people kind of avoided iterators is that when you wanted to do anything. more sophisticated with such sequences, like, I don't know, map them over them or filter them or search inside of them or whatever, at the end of the day, you would end up just effectively just copying them into arrays and then doing those operations on arrays. And in that case, well, you know, you might as well just work with arrays to begin with. And the reason for that is that all the iteration methods that we are familiar with for arrays, like map, like filter, like find, et cetera, just didn't exist or don't exist for iterators. And again, this is unlike other programming languages which have iterators which do provide such helper functions or iteration functions that you can use on top of iterators. So again, if you had like a map of stuff and you wanted to, I don't know, filter on top of it or whatever, you would end up spreading it into an array and then filtering on the array or something like that. And obviously again, then in that case, why not just use an array from the get-go? So apparently in order to finally deal with it... TC39 has moved to stage 3, the iterator helper's proposal, which what it does, it exactly provides all this missing functionality for iterators. So they specify the prototype for iterators, and on this prototype, they put all the functions that you expect, like find, like, well, actually, find, not sure about find. But I know that they let me check what they put. They put in, oh yeah, they do have find. They have sum, take, for each, to array, to create arrays, reduce. Exactly like the functions that you find on the array prototype, they now exist on the iterator prototypes as well. So you can get an iterator and then just filter it or map over it or do all those things and it's built in. and it's really nice. And we will see if it finally causes people to start using iterators in their code, or maybe that chip is sailed and we kind of missed the boat to continue with my nautical metaphors. But yeah, that's the idea. Overall, I'm personally really happy with it, but I do have a bit of criticism. And the criticism I do have is that like I said, they decided to implement it as methods on the iterator objects, which means that you chain the functions like you do with arrays So you would let's say you have an at iterator X you would do an x dot map dot filter dot find dot sum dot whatever and I guess that's kind of what most people expect because, like I said, this way it looks and feels like arrays without actually having to copy the values into arrays. But on the downside, I think that in an ideal world, they should have implemented it as functions rather than as methods so that instead of chaining using the dot operator, we would have piped it. from one function to the
Steve:
Yeah,
Dan:
next.
Steve:
I get what you're saying. I don't understand why though. What's the,
Dan:
Hopefully
Steve:
what's the
Dan:
I'm
Steve:
dip?
Dan:
explaining
Steve:
What's the benefit
Dan:
it
Steve:
of one over the
Dan:
this
Steve:
other?
Dan:
kind of
Steve:
I mean,
Dan:
well.
Steve:
I'm used to Chaney stuff all the time, whether it's in, you know, PHP or JavaScript, so what's the benefit of piping it through functions instead of Chaining?
Dan:
First of all, it's more functional. And that seems to be kind of the way where the coding world is headed. And especially when you think about how a lot of the frameworks these days work with expressions and values rather than objects explicitly, like if you think about stuff like JSX and stuff like that. But. The main advantages from my perspective are first that it makes the mechanism much more extensible. If you want to extend the mechanism that's dependent on chaining, you have to add functions to the prototype. And as we know, that's a recipe for naming collisions. So somebody will say, hey, you know, you're missing, there's another. Iteration method that I would love to have and you for some reason you didn't add it into the spec So I but I want to use it for my iterators So I will just add it to the prototype because that's the only way I can introduce it into the chain But then The ECMO script the TC 39 eventually might decide to actually add it and then they'll create the conflict and this has happened with the array methods. So if you have it as a standalone function, well then, you know, there's no chance of collision. It also makes it much easier for stuff like bundlers to drop dead code. So you only really need to bundle the functions that you use rather than having to kind of put in everything that might exist on the prototype. So there are a couple of benefits here. And so like I said, being functional and dealing with expressions and not necessarily requiring object instances for that, making it extensible and lightweight for the bundling. I actually wrote a blog post a long while back about how such a library might be implemented as a collection of pipable functions. Maybe I'll put a link in the show notes to that. But again, I guess that having it even as chain methods is better than nothing, that's for sure. Because like I said, currently iterators are almost
Steve:
Okay.
Dan:
dead, and partially for the lack of such a library. At least that's what I'm thinking. Can't prove it. The first version of this iterator helpers Will be just for sync synchronous iterators Which means that it won't you know, I talked about using iterators for sequences like Stuff coming over the network. So it's it won't be applicable for that for that You need to support a synchronous iterators and that's actually also there's also a proposal for that But that's currently only at stage two So stage three is for synchronous iterators, and stage two is for asynchronous iterators. But it really looks similar. Now what's really interesting is that Google has announced their intention to actually implement this in Chrome. So it's going to come out in Chrome version 114, 114. uh, behind a feature flag. So you would need actually to put, uh, a flag on the, on the browser's command line if you want to get it. But it does mean that we will be able to start playing with it, which will hopefully push it more quickly from stage three to stage four and actually getting it released and implemented in all the browsers. So that was the second feature, the language feature that I wanted to talk about. Uh, anything before we move on to the next one? Okay, have you ever
Steve:
I have looked
Dan:
used
Steve:
at those, haven't
Dan:
sets
Steve:
usually used them. Like I
Dan:
in
Steve:
said,
Dan:
your
Steve:
I usually
Dan:
code?
Steve:
revert
Dan:
I'm
Steve:
back
Dan:
talking
Steve:
to what I'm
Dan:
about
Steve:
familiar
Dan:
the JavaScript
Steve:
with. So I haven't
Dan:
sets.
Steve:
played with the methods too much. Although looking back, I dare say there might've been times when a set would have worked easier than all the manipulations I went through.
Dan:
Yeah, so set is this collection that's been added to JavaScript a while back, which basically is just a way for you to indicate if something is part of the set or not. So you add stuff into the set, you know, like let's say strings, you might add, you know, Dan, AJ, Steve, Chuck into a set, and then you would check. So putting in Dan or Steve would basically... You could check that they are in it and it would return true. But if you check about Amy, unfortunately, you will find false because Amy is no longer participating in the podcast. So set is really a simple way to check if things are part of a set or not. And like I said, it can be strings, it can be objects, and it's
Steve:
So
Dan:
really
Steve:
in other words,
Dan:
easy
Steve:
it's
Dan:
and
Steve:
cleaner
Dan:
simple
Steve:
than
Dan:
to
Steve:
doing
Dan:
use.
Steve:
like
Dan:
And it's
Steve:
a
Dan:
been
Steve:
if
Dan:
around
Steve:
index
Dan:
for a
Steve:
of
Dan:
long
Steve:
something
Dan:
while now.
Steve:
is
Dan:
It's,
Steve:
not equal
Dan:
you
Steve:
to
Dan:
know.
Steve:
negative
Dan:
supported
Steve:
one
Dan:
by all browsers.
Steve:
type of structure to see if something exists. And.
Dan:
Exactly. Yeah, it's simpler, it's more intentional, because when you use the set, it's really clear when reading the code what your intention is. Whereas if you're using an array and then using includes or index of to
Steve:
So
Dan:
check
Steve:
how does it
Dan:
if
Steve:
work
Dan:
something
Steve:
with
Dan:
is in it
Steve:
lists
Dan:
or not,
Steve:
of things
Dan:
you kind of need to
Steve:
like
Dan:
read the
Steve:
objects?
Dan:
code and figure
Steve:
So
Dan:
out the intent.
Steve:
often one of the things you
Dan:
It's also
Steve:
by
Dan:
more...
Steve:
Google, so in other words, if I have a list of objects and I wanna say, okay, I want all the objects that have this
Dan:
by
Steve:
key,
Dan:
reference.
Steve:
three levels down type of thing, doesn't handle stuff like that? No, okay.
Dan:
No, it's not for that. No, no, it's just by reference. It doesn't actually do any sort of comparison. But the one more thing I wanted to mention about sets is also that they're much more efficient because a mechanism implemented on top of an array is O of N, where N is the length of the array because you effectively need to essentially iterate through all the members of the array in order to check if something's in it or not. Whereas with set, they use some sort of built, I assume, implementation dependent, but they use some sort of a hash or a tree in order to create a much more efficient implementation. So the lookup is probably, let's say, log n or maybe even constant in many cases, and certainly not all of n. So So that's the big advantage of, those are the big advantages of using a set. But it always felt that something was kind of missing with sets, because when we're dealing with sets, there's a whole bunch of mathematical operations that seem natural to do. For example, you might want to get an intersection of two sets, or the union of two sets. But so far, those methods or mechanisms were not implemented as part of JavaScript, so you would have had to do them yourself, which is obviously an invitation for implementation bugs. So now they are going to be provided out of the box as methods on the set prototype. So you can just take a set. let's say I have two sets, I have a set referenced by the variable x and I have another set referenced by the variable y and I want to, you know, get a set which is the intersection of these two sets, then I can do x dot intersection, open parentheses, y close parentheses, and what I will get in as a return value is a new set which is the intersection of these two sets. Likewise, I can get a union of two sets or the difference between two sets and so forth So it's just a Collection of useful methods to have on top of sets and it's really great that it's being added to the language and again Probably long overdue, you know, we keep on talking about the fact that JavaScript is kind of missing standard library And it seems that slowly but surely, TC39 is working to rectify this. So partially, it's been doing it, let's say, with the iteration helpers or iterator helpers that I mentioned before. And it's also doing it for sets with the set methods. And that's all there is to it. It's pretty straightforward and obvious feature to add to the language. The next one. is much less obvious, but on the other hand, probably more familiar to a lot of JavaScript developers, and that's language support for decorators. That one we might have actually mentioned in previous episodes, I don't remember, off the top of my head. But anybody who's ever used Angular or let's say Nest.js or has just come to JavaScript from other languages like Java
Steve:
So what, okay,
Dan:
is
Steve:
let's
Dan:
probably...
Steve:
start out. What's
Dan:
probably
Steve:
a decorator
Dan:
familiar
Steve:
and what's the benefit
Dan:
with the
Steve:
of
Dan:
concept
Steve:
it?
Dan:
of decorators, and the implementation looks essentially the same. You... So decorator is something that you use with classes. So that's both the upside and the downside of decorators, at least in JavaScript, that they go hand in hand with classes. So if you use classes, there's a good chance you also end up using decorators. And if you don't use classes, then you'll probably never use decorators. The idea is to support something that's aspect oriented programming, which is a mechanism for managing cross cutting concerns in a kind of a clear way. I'll try to give an example. Let's say we have a whole bunch of classes in our code, which are essentially unrelated to one another. So we don't expect them to... inherit from a common base class because they're unrelated. Let's say we have a class for user and we have a class for computer. You know, we could have a class called entity or whatever, but it kind of seems odd. But let's say despite the fact that they don't have a common ancestor or base class, we want them to, we want to add common functionality to them. Let's say we want to have logging, let's say, so that every time a method is called on one of these objects, it logs, let's say, the fact that it's been called and the values of its parameters and maybe also the return back. So we want to add logging capability or another example, we might want to add the ability to serialize objects. You know, we want to control how certain fields in an object are serialized or deserialized into, let's say, JSON. So we want to add this functionality of, let's say, serialization and deserialization into these objects. So one way would be to inherit from a common object that implements serialization and deserialization. But like I said, that's kind of odd, because it's not a single object. using inheritance for that creates an association that's not really expected. Also, what would we do about the logging? In JavaScript, you don't have multiple inheritance. You can inherit from two distinct base classes. You can only inherit from one. So do we inherit from the serialization base class or from the logging base class? What happens if you want to have both? So that's the problem. And decorators kind of strive to fix that. And the way that you do it is you write the at symbol, followed by the name of the decorator in front of a class name or a method name or a field name. And it decorates, you know, respectively, either the class itself or the method or the field slash property. And... by, and the decorator name is actually just a function name. So let's say you decorated a class, the, that function is invoked with a reference to the class and some additional information. And what it returns is a replacement or a modified class that, you know,
Steve:
Now,
Dan:
that
Steve:
it makes sense.
Dan:
is the original class
Steve:
So basically, you're
Dan:
plus
Steve:
defining
Dan:
logging.
Steve:
another,
Dan:
or
Steve:
what
Dan:
plus
Steve:
do you want to call
Dan:
serialization.
Steve:
it, function method, piece of code, whatever,
Dan:
It's kind of tricky
Steve:
that
Dan:
to explain,
Steve:
you want to run. Was it
Dan:
but
Steve:
run every
Dan:
that's
Steve:
time
Dan:
the
Steve:
the class
Dan:
concept.
Steve:
is instantiated? I mean, do you add a decorator to a class and then you have to specifically call that decorator at some point, or is it something that's always run at a certain point in the class life cycle? Okay, instantiated when an object with
Dan:
It's actually run when that class is created, as it were.
Steve:
Mm-hmm.
Dan:
So, yeah, it kind of replaces, so let's say you have a class C, capital C,
Steve:
Right.
Dan:
it
Steve:
Okay,
Dan:
actually
Steve:
so it's sort of an, it's basically
Dan:
causes
Steve:
an override
Dan:
C
Steve:
is what it
Dan:
to
Steve:
sounds like.
Dan:
reference the decorated class rather than the original class. Yes, yes, exactly, it's an override. It overrides the class
Steve:
Okay.
Dan:
and it creates that override by calling a function, passing in the original class and getting back the decorated class. Now, we will put a link. It's again, it's kind of difficult to explain APIs without actually showing code, but it's actually fairly straightforward and... Like I said, it's totally in line with how this mechanism is implemented in other programming languages that support it, and also with the implementation that exists in JavaScript, in existing JavaScript frameworks and libraries like Angular, like Nest, JS, and others. So ideally, currently, these languages use a transpiler to deal with these decorators and... Ideally now they will just be able to generate the JavaScript code as is and it'll just work. So that's the concept of decorators. The last
Steve:
Sounds like a game or
Dan:
stage
Steve:
a movie or
Dan:
three
Steve:
something, right?
Dan:
item that I wanted to mention is something called shadow realms, which sounds kind of spooky or ominous. Yeah, exactly. Do you wanna come to my shadow realm? Ha ha ha. Yeah, kind of reminiscent of Shadow DOM, if you're familiar with that, if you remember that. So Shadow Realm, the idea is that you want to create a distinct global environment. And what do I mean by that? Do you know like when you create an iframe, let's say you have an iframe in your tab and it's an iframe to the same domain. So you can actually call functions directly with the inside the iframe or the iframe can call Functions that are directly inside the containing tab because they're both in the same domain But they actually have their own distinct global objects and They have their own distinct prototypes for the various built-in object types So for If you remember a lot of people well not a lot of people but people would run into Surprising issues with that sort of thing like they would try to check if some object is an array By comparing its prototype to window dot array with a capital a and it will come out as false Because it was an array that was created inside the I frame. So the its prototype was actually different It was also Window dot array, but it was a different window
Steve:
So sort of
Dan:
so
Steve:
like
Dan:
it was
Steve:
a sandbox.
Dan:
a different window dot array instance So you know funny stuff like that so? Shadow realm is a way to be explicit about this like get similar behavior, but without Needing an iframe for it so a shadow when you create Yeah, exactly. It's a sandbox you you run script inside the shadow realm, that script gets its own global and gets its own prototypes on the objects. So for example, if you want to run potentially some sort of an untrusted script,
Steve:
Yeah, it makes
Dan:
I don't know,
Steve:
sense.
Dan:
third party cookies, whatever, you can run them inside of a shadow realm instead of inside your global environment and then you have assurances that they're not polluting. your global environment in any unexpected sort of a way. I know that a lot of people have been looking for something like this for a long time. It will be interesting to see how this feature is used. Anyway, so those are the what is it five? stage three Additions to JavaScript that I wanted to talk about like I said because they're a stage three They're all going to effectively make
Steve:
Yeah,
Dan:
it
Steve:
we got
Dan:
unless
Steve:
a couple.
Dan:
there's like
Steve:
We're
Dan:
a
Steve:
getting
Dan:
last-minute
Steve:
close to an hour,
Dan:
surprise
Steve:
but yeah, we could
Dan:
or something
Steve:
drop a couple in.
Dan:
And we might expect to see them Implemented in browsers in a year from now or something like that some of them as we saw even sooner than that Do we have time, like a bit of time to go over the few stage two items? Yeah, so I already mentioned one, which was the async iterator helpers, which were like the iterator helpers, but for asynchronous iterators. So instead of just iterating over collections like a map or a set, with async iterators, you can iterate over sequences, like data coming in over the network, or a sequence of events, or stuff like that. And there's a proposal to add helpers like... map, filter, etc. for those types of iterators as well. Makes sense, you know, why if you know if you need them for one then you also need them for the other and I don't see any reason why this wouldn't get added eventually to the language. The other stage two proposal is one that's also kind of interesting in that it's how is it that this thing doesn't exist yet which is iterator.range. Think about it this way, how many times have you wanted to like create it or let's say that you wanted to create an array filled with let's say the numbers 0 to 1000 and you had to write like you know kind of obnoxious code, non-trivial code in order to do it quote unquote cleanly and efficiently. It seems like this kind of thing needs to be built in. If you want to. Iterate over a sequence of numbers, let's say and you don't want to use a for I for it You want to do it in the kind of this functional sort of a way? So that's what ranges provide you with And it's something that exists in a lot of programming languages. I think you you've got it in Python You got it in Kotlin. You've got it in a lot of programming languages that support this kind of a construct. So you do like the iterator dot range and you specify the start of the range, let's say zero and the end of the range, let's say 100 and what you get in return is an iterator that basically goes through all the values from zero to 100. And you can even specify a skip. Again, anybody who's familiar with python is like banging their head and saying how is it that something like that hasn't existed before? So, so yeah. it's pretty obvious. Again, it's kind of difficult for me to explain it without showing code. But we'll give the link, and it's pretty obvious. And the nice thing about it is that it works
Steve:
Uh,
Dan:
really
Steve:
yeah,
Dan:
nicely
Steve:
as much as it clears,
Dan:
with the
Steve:
it can
Dan:
iteration
Steve:
be without actually
Dan:
helper functions
Steve:
seeing some code.
Dan:
that I mentioned before.
Steve:
I mean,
Dan:
So you can
Steve:
we'll
Dan:
do
Steve:
deal with
Dan:
a
Steve:
the iterators,
Dan:
range,
Steve:
you know,
Dan:
and
Steve:
iterating
Dan:
then filter
Steve:
over
Dan:
on the range,
Steve:
lists
Dan:
and then
Steve:
or,
Dan:
map
Steve:
you
Dan:
on
Steve:
know,
Dan:
the range.
Steve:
arrays
Dan:
and
Steve:
generally let rays of objects
Dan:
then let's say convert it to an array.
Steve:
raise of
Dan:
If
Steve:
any
Dan:
you want
Steve:
number
Dan:
to get
Steve:
of things
Dan:
the final
Steve:
all
Dan:
result
Steve:
the time.
Dan:
as
Steve:
So
Dan:
an area
Steve:
I'd have to
Dan:
of
Steve:
get
Dan:
values,
Steve:
in and play with
Dan:
whatever.
Steve:
these a little more, but
Dan:
It's
Steve:
anything
Dan:
really
Steve:
that
Dan:
nice.
Steve:
makes it easier to pick something out of an array
Dan:
So
Steve:
is
Dan:
is it
Steve:
always
Dan:
clear?
Steve:
useful
Dan:
Hopefully
Steve:
out of a
Dan:
I
Steve:
set.
Dan:
managed
Steve:
I know
Dan:
to explain
Steve:
one
Dan:
it
Steve:
of the
Dan:
clearly
Steve:
nice things
Dan:
enough.
Steve:
about, um, Laravel is that it has a whole. class of tools for that called they call a collection but there's just a ton of different helper methods in a collection that are designed to help you get things out of your models which can be very complex you know very easily doing a sum of something or iterating over
Dan:
Yeah.
Steve:
it and doing all kinds of calculations and stuff that just you can do it a couple lines of code where without that particular class you would have to write a lot more code So yeah, iterators are always useful when you're dealing with large lists of things.
Dan:
Yeah, I think... Exactly. And I think that's the key point. We are writing ever larger and more complex and sophisticated JavaScript applications. So we expect JavaScript programming language to support this with constructs that make writing larger code bases easier. And we've talked about the lack of a standard library in the past. standard library being a collection of useful functions that you can use. And like I said, it seems that TC39 is trying to step up to the plate in this regard and kind of fill in the blanks or at least the most glaring obvious missing pieces. The last one that I want to talk about before we head on over to PICS is one that's actually in stage one. which means that there is absolutely no guarantee that it will make it into the programming language. In fact, it's been stuck in stage one for a long time, which kind of makes me fairly pessimistic about it, but I wanted to discuss it nonetheless, because when I saw it for the first time, I was actually opposed to it. And now I'm coming around to the conclusion. that I think that it's actually really needed in the language and useful. And I'm actually hoping that they'll find some way of moving it beyond stage one and actually adopting it into the programming language. And this feature is called do expressions. It often confuses people when I mention it because they assume I'm talking about do while, which is a pretty esoteric language feature as well. but one that's been part of the language from day one, because JavaScript kind of inherited it from C. But apart from reusing the same keyword, the do keyword, it actually has no relation whatsoever to the do-while loops. So let's forget about do-while loops, let's not even discuss them, and let's focus on do expressions instead. What do expressions are, are they are essentially a mechanism for writing complex expressions or actually a better way to put it would be to use statement keywords inside of expressions. What do I mean by that? In JavaScript, unlike some other programming languages, specifically functional programming languages, makes a very clear distinction between things that are expressions and things that are not expressions. And certain things, JavaScript keywords are not expressions and cannot be used as part of expressions.
Steve:
Sorry, I had the mute on there. Yes,
Dan:
For example,
Steve:
yep, I'm with you so
Dan:
the
Steve:
far.
Dan:
for loop
Steve:
Can't guarantee
Dan:
cannot
Steve:
how much
Dan:
be
Steve:
longer I'll
Dan:
part
Steve:
be with
Dan:
of an
Steve:
you,
Dan:
expression.
Steve:
but keep going.
Dan:
If you want to have a loop inside of an expression, you need to use some sort of an iteration method like a map or a filter, which returns a value. A for loop does not return a value. So far so good?
Steve:
Okay, that's what I was gonna say. You can do it just with turn areas.
Dan:
Another yeah another example of something which isn't Which can't be used inside of an expression is If
Steve:
Multi-level
Dan:
statements,
Steve:
turn areas,
Dan:
you
Steve:
yeah,
Dan:
know if
Steve:
they're
Dan:
we
Steve:
confusing.
Dan:
wanted to Have conditionals Instead inside expressions we had to use a ternary expressions
Steve:
All right.
Dan:
Yeah, but that's much less readable, especially when it becomes complex. I'm sure you've seen situations where it's question mark, colon, question mark, colon, question mark, colon, and so forth. And it... Yeah. And ifs are more explicit and easier to read, but they can't be used as an expression. So, do expressions change that? You do, let's say, let x equals do open curly brackets, and from that point on, until the end of the curly brackets, everything in it behaves differently, behaves as if it's part of an expression. It's kind of like doing, using an iffy.
Steve:
Yes,
Dan:
You
Steve:
immediately
Dan:
know
Steve:
invoking
Dan:
a self-invoked
Steve:
function
Dan:
anonymous
Steve:
expression.
Dan:
function
Steve:
Isn't that what that stands for?
Dan:
You know you where you can you want to assign some? Some value into a variable and it's a sophisticated computation
Steve:
Yep.
Dan:
and it's hard to do is a simple expression But you
Steve:
Yeah,
Dan:
don't
Steve:
we had to
Dan:
want
Steve:
use them
Dan:
to
Steve:
a lot
Dan:
create
Steve:
with jQuery.
Dan:
a global
Steve:
Um, if we wanted,
Dan:
Function for
Steve:
uh,
Dan:
it. It's
Steve:
I know
Dan:
just
Steve:
it inside
Dan:
it's a
Steve:
the
Dan:
very
Steve:
Drupal world,
Dan:
localized
Steve:
that was how we
Dan:
computation.
Steve:
implemented things was with
Dan:
So
Steve:
if he's
Dan:
you might use an
Steve:
where you
Dan:
iffy
Steve:
had your function
Dan:
for it.
Steve:
and
Dan:
You
Steve:
then
Dan:
know
Steve:
the
Dan:
what I'm talking
Steve:
parentheses
Dan:
about
Steve:
afterwards that caused it to be invoked.
Dan:
Yeah, but there's a lot of boilerplate associated with it when you're doing it. You know, there's a lot
Steve:
I'm out.
Dan:
of open and close parentheses in
Steve:
Right,
Dan:
order to get it to
Steve:
I can
Dan:
work.
Steve:
see that.
Dan:
And it's always slightly confusing, especially for newbies. Yeah. Yeah, Douglas Crockford always referred to them as gonads, hanging on at the end of the function of the iffy. But yeah, so do expressions actually do away with all these parentheses, but it goes beyond that because inside the do expressions, semantics actually change. So an if can become a part of an expression. And the value of the if, you don't need to put returns in it actually, because the last value that you get to, that's the value of the expression.
Steve:
So
Dan:
So
Steve:
the
Dan:
you
Steve:
expression
Dan:
might do
Steve:
has.
Dan:
something like if... something, you know, zero else 42. And you don't need to put the return, you just write that value in it and that gets returned quote unquote as the value of the do expression. Again, difficult to explain without showing the code. We'll put a link to the actual proposal. So it actually changes the semantic of the language inside. Yeah, but it doesn't use the return value. It's just the last value inside. You just write the value and that last value instead of basically doing nothing gets quote unquote returned as the value of the do expression. So you could do if something one else, if three else, if 42 else, zero stuff like that. Now that's the reason that I initially disliked this proposal because inside the do expression it changes the semantics of the language and that's kind of scary. Certainly for newbie programmers where they suddenly see familiar statements working differently. And that's why when I saw it I said, okay cool, but I don't want it but now like I said, I do actually want it and There are a couple of reasons The first reason is that we are these days we're creating in our JavaScript code really sophisticated expressions much more so than we've ever done and The reason for that is JSX because when you return JSX, that's an expression. And if you want to have conditionals inside of the JSX, which you often do, render this or render that based on some value, then these days you use ternary expressions and it can get pretty hairy. And if you want to do loops, then you have to use maps and filters. You can't use four. If you do want to use for, you have to kind of explicitly split it into like its own separate function or something, which is kind of annoying. And do expressions solve all
Steve:
You
Dan:
that.
Steve:
can use an expression,
Dan:
You
Steve:
but
Dan:
can
Steve:
you're limited
Dan:
put a do
Steve:
by
Dan:
expression
Steve:
space. Where
Dan:
inside of
Steve:
being
Dan:
your
Steve:
able
Dan:
JSX
Steve:
to do that, I could see would
Dan:
and all of
Steve:
provide
Dan:
a sudden
Steve:
a lot more flexibility.
Dan:
inside the expression, you can actually use ifs, which makes the code a lot more readable, I have to say. from examples that I've seen in the proposal itself. So JSX and JSX is, I know that you'll come from the view world that kind of skews JSX, you know, popoos it, whatever, call it whatever way you want, but effectively all other frameworks are kind of adopting it. So obviously React, but also Solid, then Quick and others. So JSX is kind of a big part of the web development these days. And anything which can make JSX better, I think the programming language needs to align with the way in which developers are using it. And a large portion, a very large portion, of the JavaScript developers, maybe even the majority of them, are using JSX and therefore can really benefit from do expressions. Do expressions actually have two additional benefits, which I'll explain really briefly. One is that they inherit the ability to call a weight from their containing function. So if their containing function is async, they can await and the await behaves as you would expect. It actually blocks the computation of that expression. and which is kind of more much more challenging to do with an iffy So so that's one big benefit of it And the other is that you can actually use the return value the return statement inside a do expression And it will actually return out of the containing function. So that, and that's really cool. You can really short circuit from the middle of an expression, which can be really useful in some cases. So it definitely has benefits. And that's why I've gone from, you know, being against it again, for changing the semantics of the language to being for it, because I think it's just really beneficial. for the way, given the way in which a lot of developers are using JavaScript these days. Yeah. So that's it. Those are the proposals that I wanted to talk about today. Hopefully our listeners found it interesting. I know that some people, like AJ, for example, who unfortunately couldn't be here, kind of don't like the fact that JavaScript continues to grow in this way. And I can totally understand why. Because JavaScript has become a much more complex and sophisticated programming language than it used to be. Now, obviously, you can choose to avoid certain aspects of it that you dislike, but you can't really maybe prevent your colleagues from using it, which means that you'll end up having to deal with these additions, whether you like it or not. So I can understand where AJ is coming from, but I do think... that at least some of these additions are making the language better. Definitely the ones that are effectively creating a standard library on top of it, which is like I said something that I thought was sorely lacking, and I'm really happy to see this void being filled. So yeah, that kind of concludes my exposition of these new JavaScript features. But we're nerds. Yeah, I think we're both. I don't know. What did it say? Okay. It reminds me of a joke that I know, where the pessimist sees the glass half empty, the optimist sees the glass half full, and the programmer says, we could have used a smaller glass. Got it. Yeah, that is true. Yeah. Okay, so I spoke at a tech conference recently called J Nation in Coimbra in Portugal. And one of the great things about conferences, at least the way in which I attend them, is now that my kids are older and I don't have to worry about what goes on with them, is that we actually turn such, you know, speaking opportunities into vacations. So my wife joined me and we toured for about a week and a half through Portugal. Funnily enough, we were actually supposed to do this like three years ago, but then COVID happened. So we were kind of also making up for that missed vacation from three years ago. And I have to say that Portugal is amazingly beautiful. and highly recommended. We went to Lisbon and Sintra and Obidosh and Porto and the Douro Valley and Coimbra where the conference was held. And it's just a lovely country. One of the great things about it is that Portugal did not really go through a really destructive war since like the middle ages. So all the castles and old cities and old buildings are preserved. So you get to see a ton of history there because you know in other parts of Europe everything is effectively reconstructed because everything kind of got demolished in the Second World War. And also the nature is beautiful like the Doro Valley is amazingly beautiful. So I highly recommend Visiting Portugal and it's my first pick Um What's my next pick? Oh my next pick is that i'll actually be speaking at An additional two conferences pretty soon One is in about a week and a half. So it'll probably in the past by the time this episode comes out And it's called the react next uh in uh here in tel aviv in israel, it's uh Pretty big conference. It's over a thousand attendees and I know that they're sold out. Our friend Tejas, who I hoped could be an extra panelist, but it seems he's too busy to join us most of the time, is also actually going to be giving the keynote there. I'll be speaking there as well. I'll actually be talking about how different frameworks these days are striving to overcome the performance cost of hydration. It's something that I think I actually spoke about in a past episode on here on JS Jabber, but I don't remember which one. So probably we'll need to look up afterwards. Yeah, for sure. Yeah, yeah. Which brings me so that's so and I'll also be talking at another conference actually giving the same talk at another conference in Zurich in Switzerland. It's called the front conference Zurich and which actually gives me the opportunity to go visit Austria and Switzerland. So here we go again. And hopefully that will be my pick in the future. episode about how great these countries are to visit and tour through. And my final pick for today is that you just mentioned QUIC. Mishko Haver, who created QUIC and also previously created Angular, actually visited Israel last week. We've been online friends or virtual friends, and we finally got to meet face to face. And you know... I attended his talk at the meetup and then we went out for drinks afterwards and it was really great. He's a great guy. It was a lot of fun talking with him, both in general and also about the great things that they're doing in QUIC. So I'll just give QUIC a shout out and I'll say that if you're looking for a framework which provides a great performance out of the box, essentially whatever code you write, then QUIC is something that you should definitely be looking at. And I think we will have Mishko again in an upcoming episode. So we'll get a chance to grill him some more about the great and crazy things that they're doing in that framework. And those would be my picks for today. For sure. Bye.