JavaScript news in 2022

javascript2 min

byLucas Santos

This page was machine translated. Read original / Suggest a fix

Every month we get tons of updates in our favorite languages, and JavaScript is no exception.

I made a video explaining a bit more about how JavaScript’s release process works for new features. If you haven’t watched it yet, I strongly recommend it so you can better understand how everything works.

Play

With that said, the 2022 version of ECMAScript—the spec behind JS—is incredible, and I’ll explore all the major features with you!

The .at() method for all indexables#

One of the simplest but also coolest additions is the new .at() method on arrays and any other native indexable, like strings.

What it does is give you the item at the requested position in an array. For example:

const cart = ['banana', 'apple', 'pear']
cart.at(0) // banana
cart.at(-1) // pear
// Out of bounds
cart.at(100) // undefined

And it works for any indexable, so if we have a string:

const phrase = 'The quick brown fox jumps over the lazy dog'
phrase.at(0) // T
phrase.at(-1) // g

Capture indices in RegExp#

Now, besides returning the match from your regex, the RegExp constructor also returns a list of indices showing where that match started and ended. For example:

const input = 'abcd'
const match = /b(c)/.exec(input)
const indices = match.indices
indices.length // 2
matches.length // 2
// The number of indices equals the number of matches
indices[0] // [1,3] start/end of the first match "b"
input.slice(indices[0][0], indices[0][1
]) // same as match[0]

Object.hasOwn#

A simpler variation of Object.hasOwnProperty that returns true for all properties that belong directly to an object (not inherited):

const books = {}
books.pages = 123
Object.hasOwn(books, 'pages') // true
Object.hasOwn(books, 'toString') // false
// The 'in' operator checks all properties
'pages' in books // true
'toString' in books // true

Error causes with Error.cause#

This is one of the major changes and one I think will be most useful. This new property on the error class shows you what caused the error.

const error = new Error('An error', { cause: 'The cause of this error' })
error instanceof Error // true
error.cause // 'The cause of this error'

The main use case is avoiding passing the error object directly:

try {
doesNotWork();
} catch (err) {
throw new Error('doesNotWork failed!', { cause: err });
}

Top-level await#

This has been available in Node.js for a while, but since we have ESModules we can now do top-level await, that is, an await outside of an async function:

index.mjs
// fails in the old implementation
await Promise.resolve('🍎');
// → SyntaxError: await is only valid in async function
// the workaround we usually do with IIFE
(async function() {
await Promise.resolve('🍎');
// → 🎉
}());
// new top-level await implementation
await Promise.resolve('🍎') // '🍎'

Class field declarations#

We FINALLY now have class property declarations outside the constructor. That means we can declare and assign a value to a class property without needing a constructor with this.prop = prop.

This was already pretty common in TypeScript, but now it’s coming natively to JavaScript:

class MyClass {
/*
instead of:
constructor() { this.publicID = 42; }
*/
publicID = 42; // public field
/*
instead of:
static get staticPublicField() { return -1 }
*/
static staticField = -1;
// private static fields
static #privateStaticField = 'private';
// private methods
#privateMethod() {}
// static initialization with static declaration blocks
static {
// Runs when the class is created
}
}

Class field checks through reflection#

This is a tricky use case, but when we tried checking a class property through a static initialization block, we’d get an error saying the class wasn’t initialized or the property doesn’t exist. This got fixed:

class C {
#prop;
#method() {}
get #getter() {}
static isC(obj) {
// using 'in'
return #prop in obj && #method in obj && #getter in obj;
}
}