ECMeowScript–what’s new in JavaScript explained by cats

While not quite the bumper update of 2015, the most recent iteration of JavaScript, ES2020 features a number of new language features, small and large. From the ability to handle very large integers, to additions to asynchronous JavaScript, to a myriad of cleanups and refinements of the language.

In this presentation, Open Web advocate and front-end engineer Tomomi Imura gets us up to speed with the latest iteration of JavaScript, with a little whimsy, because we could all use a bit of that right now.

ECMeowScript–what’s new in JavaScript explained by cats

Tomomi Imura, Software Engineer

Appropriately enough Tomomi begins by introducing us to her feline assistant, Jamie. Who looks like Maru’s cousin!

Tomomi is going to talk about things you may or may not know about JavaScript, illustrated with examples about cats. You may have seen earlier projects about HTTPcat, Raspberry Pi Kittycam or her cartoons – all cat themed.

JavaScript is technically EcmaScript with cats – aka. EcmeowScript! Yes she knows it’s silly 😉

Let’s begin with ES6/ES2015. This was the sixth edition of EcmaScript, with a lot of major changes and additions including arrow functions, let and const, promises, template literals and much more.

While not part of ES6, Intl.DateTimeFormat() was introduced around the same time and is worth mentioning as well.

Reiwa – JavaScript International Date Format and Japan’s New Imperial Era

So let’s get into the -JavaScript-cats!

const cats = [
{name: 'Jamie', type: 'tabby', img: '00_jamie.jpg'},
{name: 'Leia', type: 'tuxedo', img: '01_leia.jpg'},
{name: 'Alice', type: 'tortoiseshell', img: '02_alice.jpg'}

First example, creating an array of cat names from an array of cat objects. In ES5 you’d have done something like loop through the array and push values; but ES6 offers a couple of new ways to do this.

.map() lets you create a new array by mapping values from the old array. It runs a function over all the values and builds an array from the function return. That’s pretty neat but then Arrow Functions let you write it with extremely concise syntax, by omitting parens when there is only one argument; and implicit return for one-liners. =>;

You could also achieve this result with Object Destructuring, which makes it easy to create variables with values from an object.{name}) => name);

This is a particularly useful technique when an API sends back a chunk of JSON and you only want part of it.

Next up we have the spread operator (“three-dots” ...) which allows an iterable (array or string) to be expanded. Great for easily including an array in a new array.

catNames = ['Jamie', 'Leia', 'Alice'];
const newCatNames = [...catNames, 'Yugi','Snori'];

The new array contains all five cat names.

Spread syntax can be used for a variety of useful (and concise) tricks:

Blog: Spread Syntax ‘Three-dots’ Tricks You Can Use Now

Next we have the map object – not the same as from earlier, this is a hashmap. This has useful methods like get, set and has which provide intuitive ways to work with your data.

ES6 had lots of great stuff, but now let’s look at ES7. It was a relatively small update but brought in the Exponentiation Operator (**) and Array.prototype.includes()

a ** b is the same as Math.pow(a, b) (Math paws!)

Array.prototype.includes() is a neat boolean alternative to the clunky ES5 indexOf check that we all know and…use.

const coatColors = ['solid', 'bicolor', 'tabby', 'calico', 'tortoiseshell'];
coatColors.includes('tabby') // true
coatColors.includes('neon') // false
// VS
coatColors.indexOf('tabby') > -1 // true
coatColors.indexOf('neon') > -1 // false

Moving on to ES8 – this was a bigger update. Async/await, padStart()/padEnd(), trailing commas, Object.entries(), Object.values(), enumerable property values, shared memory and atomics.

Async/Await is basically syntactic sugar on top of promises, pausing execution of the async function to wait for the pass Promise’s resolution.

A silly example is pseudocode for a robot litterbox, that has to wait for the cat to leave to start a cleaning cycle.

const runLitterRobot = async() => {
await cat.poop();

padStart and padEnd allow you to pad the start or end of a string, to a specified length.

const boxStr = '?';
boxStr.padStart(4, '?');
boxStr.padEnd(4, '?');

While cute, a more practical example is zero-padding:

const str = '5';
str.padStart(4, '0'); // '0005'

These work correctly in right-to-left languages, which is also they are not called padLeft and padRight.

Trailing commas aren’t really something you need to memorise, but trailing commas no longer cause an error in several cases where that was mostly just an annoyance.

const makeFood = (param1, param2,) => {..};
makeFood('tuna', 'salmon',);

On to ES9/ES2018. Spread & Rest properties, RegEx improvements, Asynchronous iteration and Promise finally()… but not enough cat jokes here so let’s move on!

ES10/ES2019 String.prototype.trimStart() and trimEnd(), Array.prototype.flat() and flatMap(), Object.prototype.fromEntries(), Function.prototype.toString(), well-formed JSON.stringify(), better array sort().

String.prototype.trimStart() and trimEnd() remove whitespace from the start and end of strings.

const greetStr = ' meow ';
greetStr.trimStart(); // 'meow '
greetStr.trimEnd(); // ' meow'

Array.prototype.flat() flattens arrays to one level by default, so you can specify the depth to flatten more levels.

const colors = [['black', 'gray', ['orange', 'light orange']], 'bicolor', 'calico'];
const colors1 = colors.flat();
const colors2 = colors.flat(2);

flatMap is similar, but it maps each element before creating the new array.

ES11/ES2020 – the latest version includes BigInt, globalThis, Dynamic import, Nullish coalescing operator (??), Optional chaining (?), Promise.allSettled(), String.prototype.matchAll(), Module export. These are still pretty new so Tomomi can’t cover the entire suite just yet.

globalThis is a standard property for accessing globals across the different JavaScript environments, particularly browsers vs nodejs (which just has global).

?? is a neat way to access falsy values, but avoiding issues with nullish values.

BigInt is a very big cat, letting JavaScript handle much bigger numbers than Number. You can see the effect by trying to increment beyond MAX_SAFE_INTEGER. The notation for BigInt is a trailing n.

let max = Number.MAX_SAFE_INTEGER; // 9007199254740991
max++ // try this, doesn't work
let largerThanMax = 9007199254740992n;
largerThanMax++ // 9007199254740993n
largerThanMax++ // 9007199254740994n
largerThanMax++ // 9007199254740995n

A real world example of needing these numbers is Twitter hitting JavaScript’s number limit while generating tweet IDs. We tweet a lot…

Running out of time and cat puns… but hopefully we are all feline great about by now!