DEV Community

Cover image for New ES2021 JavaScript features (now available)
Yohann Legrand
Yohann Legrand

Posted on

New ES2021 JavaScript features (now available)

Photo by James Harrison

☕️ Read this article on my blog

In case you missed it, the new ES2021 JavaScript features have been recently approved by the Ecma General Assembly and are now already supported by recent versions of the most popular browsers, yeay 🎉

📝 Note: For older browsers support (which you should definitely care about), you will need to set up your project with the Babel compiler. Babel will "translate" those new features to some JavaScript that older browsers can understand. Try it out on the Babel homepage!

Logical Assignment Operators

📙 Proposal

1. Logical nullish assignment (??=)

x ??= y will only assign y to x if x is nullish (i.e. null or undefined)

// Example 1: x is nullish
let x
const y = 'Chuck Norris'
// ✅ x is assigned 'Chuck Norris'
x ??= y

// Example 2: x is not nullish
let x = 1
const y = 2
// 🔴 x is not assigned 2, its value remains 1
x ??= y 

// Translates to this
x ?? (x = y)
// or this
if (x === null || typeof x === 'undefined') {
    x = y
}
Enter fullscreen mode Exit fullscreen mode

2. Logical OR assignment (||=)

x ||= y : this one is similar to ??=, except it only assigns y to x if x is falsy

// Example
let x = 0
const y = 2
// ✅ x is assigned 2
x ||= y

// Translates to this
x || (x = y)
// or this
if (!x) {
    x = y
}
Enter fullscreen mode Exit fullscreen mode

3. Logical AND assignment

x &&= y is the exact opposite of x ||= y : it assign y to x if x is truthy

// Example
let x = 1
const y = 2
// ✅ x is assigned 2
x &&= y

// Translates to this
x && (x = y)
// or this
if (x) {
    x = y
}
Enter fullscreen mode Exit fullscreen mode

Numeric separator

📙 Proposal

I have been waiting for this one for a long time. It simply improves readability of big numbers, without changing anything to performance nor equality:

// Before
const bigNumber = 19432482347 // => ??? hard to read

// Now
const readableBigNumber = 19_432_482_347 // here we go, much better 😇
Enter fullscreen mode Exit fullscreen mode

String.replaceAll

📙 Proposal

String.prototype.replaceAll(searchValue, replaceValue)

Until now, we had String.prototype.replace which replaced the first occurrence * of a pattern in a string. In order to replace *every occurrence, we had to use a regular expression with the global flag:

// String.prototype.replace (searchValue, replaceValue)

const str = "This is a test, I repeat, this is a test"
str.replace(/test/g, 'success')
// output: This is a success, I repeat, this is a success
Enter fullscreen mode Exit fullscreen mode

There is also a trick which consists of using the split and join methods:

str.split('test').join('success')
// output: This is a success, I repeat, this is a success
Enter fullscreen mode Exit fullscreen mode

This can now be done using the replaceAll method:

str.replaceAll('test', 'success')
// output: This is a success, I repeat, this is a success
Enter fullscreen mode Exit fullscreen mode

Just like with String.prototype.replace, searchValue can be a regular expression, but it has to include a global flag, otherwise it will throw an exception. As mentioned in the proposal:

This is done to avoid the inherent confusion between the lack of a global flag (which implies "do NOT replace all") and the name of the method being called (which strongly suggests "replace all").

Promise.any

📙 Proposal

Promise.any([promise1, promise2, promise3]).then(...).catch(...)

Promise.any is a new promise method that takes an array of promises and resolves with the value of the first promise to successfully resolve. It will throw an AggregateError if all the promises are rejected.

This snippet (from the proposal) checks which endpoint responds the fastest, and then logs it:

Promise.any([
  fetch('https://v8.dev/').then(() => 'home'),
  fetch('https://v8.dev/blog').then(() => 'blog'),
  fetch('https://v8.dev/docs').then(() => 'docs')
]).then((first) => {
  // Any of the promises was fulfilled.
  console.log(first);
  // → 'home'
}).catch((error) => {
  // All of the promises were rejected.
  console.log(error);
});
Enter fullscreen mode Exit fullscreen mode

WeakRefs and Finalizers

📙 Proposal

Those new features come together in the same proposal in order to add the ability to:

  1. create weak references to objects with the WeakRef class
  2. running user-defined finalizers after objects are garbage-collected, with the FinalizationRegistry class

I won't go into more details about those features as they are quite advanced, and, as the proposal states:

Their correct use takes careful thought, and they are best avoided if possible.

But if you're interested, feel free to read more in the original proposal.


That's all for today folks, have a fantastic day!

With 🧡, Yohann

Top comments (0)