Skip to content

Instantly share code, notes, and snippets.

@jorendorff
Last active October 7, 2023 23:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jorendorff/06363f3c08b9157b09030a3fc93440f1 to your computer and use it in GitHub Desktop.
Save jorendorff/06363f3c08b9157b09030a3fc93440f1 to your computer and use it in GitHub Desktop.

ICYMI: New JavaScript Language Features

Let's talk about JavaScript.

Here are five new language features that are available in Firefox Nightly. These are new things that weren't there the last time we did this.

I'm going to move quickly, because although the things are small, there are several of them.

catch variable is now optional (Firefox 58)

You're probably familiar with try/catch. It looks like this.

try {
    data = JSON.parse(blob);
} catch (errorObject) {
    alert("Your blob is invalid. This incident will be reported.");
}

The new feature, which is very tiny, is that this variable name here, errorObject, note that we're not using it anywhere, so why even have that; well, as of Firefox 58, you can omit it:

try {
    data = JSON.parse(blob);
} catch {
    alert("Your blob is invalid. This incident will be reported.");
}

Of course, if you do this, there's a chance that you're a bad person, and if you've ever tried to debug, for example, a web page... then you know what I mean.

So, use sparingly.

Moving on...

Intl.RelativeTimeFormat (Firefox 58)

TODO

trimStart/trimEnd (Firefox 61)

Well the standard committee did something bad. They standardized some string methods called trimLeft and trimRight. trimLeft removed whitespace from the beginning of a string, and trimRight was for removing whitespace from the end of a string, as I am now indicating, by raising my left hand.

Despite being the recipient of a top-notch kindergarten education, telling my left from my right still takes me approximately five seconds each time, and those are five seconds I would rather spend cussing at Phabricator or maybe even writing code.

Also, if you're writing Urdu, or Arabic, or Hebrew or Persian, the beginning of a string is on the rrrrright. Right? Right.

These methods now have new and improved names. Use these. Not those. Next slide.

import.meta (Firefox 62)

JavaScript modules continue progressing slowly towards world domination.

As everyone knows, sometimes you're writing a module and you suddenly need its filename. Like maybe there's some data that goes along with the module, and the module needs to load the data. Well, you need the URL. Right?

import.meta is for that. It's an object provided by the platform to every module it loads. And the platform gets to put whatever it wants in there. The only thing you'll find in it, so far, is import.meta.url. It's a string, so you're probably going to do RegExps to it.

let things = fetch(
    import.meta.url.replace(/[^\/*]$/, "things.json")
);

I just have to be OK with that.

array.smoosh() (Firefox 62)

Now the fun stuff.

I love munging data. It's just so mungible. Frequently I find, though, that my data is in the wrong shape. Like it's a square

let data = [[1, 6, 9],
            [3, 4, 7],
            [5, 2, 8]];

when what I need is these numbers, but in one long, flat, noodle-like shape. Well now there is a method for that.

>> data.flat()
[1, 6, 9, 3, 4, 7, 5, 2, 8]

It turns an array of arrays into just an array.

Funny story, the standard committee wanted to name this method .flatten(), after a lake in Sweden, but unfortunately flatten was already taken, the year 2007 is basically squatting on this method name, you can't have it. https://bugzilla.mozilla.org/show_bug.cgi?id=1443630. So they briefly considered naming it .smoosh(), and after a brief but well-attended twitter outrage party, they settled on .flat().

flat takes an argument that tells how many levels of nested arrays are being smooshed; it defaults to 1. The only reasonable values to pass to it are 1 and Infinity, and I'm-a give you the side-eye if I see you fooling around with Infinity mode. Like, "you're meddling with powers you can't possibly comprehend".

Even better is the .flatMap() method, seriously, ask me about .flatMap() sometime, but not right now.

Object.fromEntries(map) (Firefox 63)

I don't know if you know this about JavaScript, but there's this whole concept of iterators and iterable values. And one of the nice things about that is that converting data from one form to another is weirdly easy now.

Object.fromEntries is a new built-in function for turning an iterable value into an object. To use this, you need a collection of key-value pairs. For example, maybe you have an array of arrays:

[['a', 1], ['b', 2], ['c', "ponies"]]

Right? and Object.fromEntries just takes this set of key-value pairs and turns them into an object, like this.

js> Object.fromEntries([['a', 1], ['b', 2], ['c', "ponies"]])
({a:1, b:2, c:"ponies"})

ReadableStream (Firefox 65)

Streams are a little bit hard to explain. How do I say this. Streams are basically a series of tubes... no.

Streams are data in motion. A stream might be a series of events, a file coming in bit by bit over the network, it could be audio, video, JSON blobs. It's a very broad concept.

But just one example here. You know how you can use the fetch API to fetch a file off the network.

let response = await fetch("hold_music.ogg");

Well starting in Firefox 65, there will be a new thing, response.body, which is a stream object.

What can you do with a stream object? Well, you can create a stream reader and just read data from it.

let reader = response.body.getReader();
let chunk = await reader.read();

But more often, you'll make pipelines. And this is what streams are really for. You don't create a reader; you use these high-level operations. Write .pipeThrough() or .pipeTo() and just tell the data where to go. When all this is done, you'll be able to implement your own pipeline filters, your own sources and sinks.

And just generally, anywhere the web platform wants to talk about flowing data from now on, whether that's service workers, or the Request API for uploading data to a web site, now we know what type of object all those APIs are going to use. They'll use streams.

The stream API is, well, there's a lot going on. That's because it's designed to work well whether your data source is synchronous or asynchronous, whether data is being pushed or pulled, whether it's bytes or objects, and yet you can still pretty much snap any two streams together and data will flow. Streams are cancelable, streams do queue management for you, streams track error states for you, streams can do backpressure for you. This API is more informed by actual practical concerns than the Savage Love podcast. It's one of the wonders of the world, and the first pieces are shipping in Firefox 65, with more to come.

Thank you

I would like to take this opportunity to thank the volunteers who implemented many of these features.

As you know, we have a team that works on JavaScript. But we are also incredibly fortunate to have dedicated, technically excellent contributors. Volunteers and staff alike, we'd love to hear from you, so don't be a stranger.

Thanks for listening.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment