Top 8 Features of ES2021 Every Developer Must Know

Rajeshwari Pandinagarajan - Aug 9 '22 - - Dev Community

ES2021 is the 12th ECMAScript version approved by the TC39 committee. It includes some exciting features every JavaScript developer should know. So, in this article, I will discuss some of the highlights of ES2021 to give you a better understanding.

Promise.any

The promise.all() was introduced with ES2020 to run multiple promises concurrently and act when they were all settled (fulfilled or rejected). With ES2021, Promise.any() was introduced, which can handle an array of promises.

The Promise.any() method takes a list of promises and returns the value of the first promise that is resolved. In the following example, we pass two promises to the Promise.any() method, and it will give an output as soon as the first promise is resolved, since it has the minimum waiting time.

// When all the promises are passed.
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 10000, "100 second");
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 20000, "200 second");
});

let promises = [promise1, promise2];

Promise.any(promises).then((value) => {
  console.log(value); // outputs “100 second”
})
Enter fullscreen mode Exit fullscreen mode

If none of the queued promises resolves, the Promise.any() will return a rejected promise returning an AggregateError , a collection of all errors found.

// When all the promises are rejected.
const promise1 = new Promise((resolve, reject) => {
  setTimeout(reject, 1000, "100 second");
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(reject, 2000, "200 second");
});

let promises = [promise1, promise2];

Promise.any(promises).then((value) => {
  console.log(value);
}).catch((err) => { console.log("error: " + err) }) 

// outputs error: AggregateError: All promises were rejected
Enter fullscreen mode Exit fullscreen mode

AggregateError

AggregateError is an error subclass that combines multiple errors into a single object.

// Syntax
AggregateError(Array<Error>, message);
Enter fullscreen mode Exit fullscreen mode

An AggregateError is generated if all promises are passed to promise.any() fail, following a message describing the error.

// Creating an AggregateError.

try {
  throw new AggregateError(
    [new Error("an error"), new TypeError("Typeof error for some field")], "common error message");
} 
catch (e) {
  console.log(e instanceof AggregateError); // true
  console.log(e.message); // "common erro message" console.log(e.name); //"AggregateError" console.log(e.errors); //[Error: "an error", TypeError: Typeof error for some field]
}
Enter fullscreen mode Exit fullscreen mode

As shown, AggregateError allows you to retrieve the promise messages that contributed to the error using AggregateError.errors.

WeakRef and Finalizers

WeakRef stands for weak references. Weak references commonly help us to build caches or mappings to larger objects. A WeakRef creates a weak reference to the object passed to it. Since a WeakRef variable is the only reference to an object, the JavaScript engine can safely remove it from memory and free up space when the browser does garbage collection.

Refer to the following code.

//WeakRef variable value can be accessed via the deRef method.
const weakRef = new WeakRef({ 
  age: 13;
});

console.log(weakRef.deref().age)

// output: 13
Enter fullscreen mode Exit fullscreen mode

Note: Please avoid using WeakRef as much as possible since it does not have a guaranteed behavior.

WeakRef and finalizers are two features that go together. The FinalizationRegistry method allows you to request a callback after an object has become unreachable (garbage-collected).

First, define a registry with the callback you want to run. Then, call the .register method on the defined registry with the object you want to observe. It will let you know exactly when the memory of the object is freed by the garbage collector.

Refer to the following code.

const registry = new FinalizationRegistry(value => {
  console.log("Finalizer");
});

registry.register({object: "Do Something"}, "testObject");
Enter fullscreen mode Exit fullscreen mode

Here, the object passed to the register() method is weakly referenced, so when the value is garbage collected, the second parameter is passed to the finalizer (testObject).

Numeric separators

This new feature allows you to use underscores as separators for the numeric literals. It increases the readability of the numbers by separating groupings of numbers visually.

Refer to the following example.

// A billion
const amount = 1000000000; // Previous
const amount = 1_000_000_000; // With ES2021

// Hundreds of millions     
const amount = 1475938.38; // Previous
const amount = 1_475_938.38; // With ES2021
Enter fullscreen mode Exit fullscreen mode

This is much easier to read now. This does not affect performance or equality. 1000000000 is still equal to 1_000_000_000.

String.protype.replaceAll

The replaceAll method replaces all pattern occurrences with the replacement passed to it. The pattern parameter can be a string or a regex pattern, and the replacement parameter can be either a string or a function.

The replaceAll method is an improvement to the String.replace method, which can only replace the first occurrence of the pattern.

Before

const message = 'hello+good+morning';
const messageWithSpace = message.replace(/\+/g, ' ');

// hello good+morning
Enter fullscreen mode Exit fullscreen mode

After (with method replaceAll)

const message = 'hello+good+morning';
const messageWithSpace = message.replaceAll('+', ' ')

// hello good morning
Enter fullscreen mode Exit fullscreen mode

Logical Assignment Operators

Three new logical assignment operators were introduced in the ECMAScript 2021 update. These operators are pretty similar to the existing logical operators, and they help assign values to variables in a single line.

  1. Logical OR assignment operator ||=
  2. Logical AND assignment operator &&=
  3. Logical nullish assignment operator (??=)

Logical OR assignment operator (||=)

p ||= q

// This is exactly identical to the below expression.
if (!p) {
  p = q
} 

// If p is false, q will be assigned to it. Otherwise, p is left at its original value.
Enter fullscreen mode Exit fullscreen mode

Logical AND assignment operator (&&=)

p &&= q

// This is exactly identical to the below expression.
if (p) {
  p = q
} 

// If p is true, q will be assigned to it. Otherwise, p is left at its original value.
Enter fullscreen mode Exit fullscreen mode

Logical nullish assignment operator (??=)

x ??= y
Enter fullscreen mode Exit fullscreen mode

This only assigns y to x if x is either null or undefined.

Private Accessors

Private accessors work very similarly to private methods. So, let’s create a simple class with a private method to understand the difference.

Previous versions

class ExampleClass {
  MyMethod1() {
    console.log("Public method")
  }
  #MyMethod2() {
    console.log("Hidden method")
  }
}

const exampleClass= new ExampleClass ()

exampleClass.MyMethod1()
exampleClass.MyMethod2()

// output
// Public method
// exampleClass.MyMethod2 is not a function.
Enter fullscreen mode Exit fullscreen mode

In the previous ECMAScript versions, we can’t call MyMethod2(), since it is a private method. If you run the previous code, it will give an error saying that the exampleClass.MyMethod2 is not a function.

With ES2021

With the ES2021 updates, we can create a new public method called inside the class (callAll() ), and access the private method.

class ExampleClass {
  MyMethod1() {
    console.log("Public method")
  }
  #MyMethod2() {
    console.log("Hidden method")
  }
  callAll() {
    this.MyMethod1()
    this.#MyMethod2();
  }
}

const exampleClass = new ExampleClass()
exampleClass.callAll(); 

// output
// Public method
// Hidden method
Enter fullscreen mode Exit fullscreen mode

Like private methods, we can now define getters and setters in JavaScript, making them only accessible inside a class or by an instance created.

class ExampleClass {
  get #Greeting() {return "Hello Good Morning !" 
  }

  get viewGreetingMsg() {
    return this.#Greeting
  }
}

let exampleClass = new ExampleClass();
console.log(exampleClass.viewGreetingMsg);

// Hello Good Morning !
Enter fullscreen mode Exit fullscreen mode

dateStyle and timeStyle options for Intl.DateTimeFormat

The Intl.DateTimeFormat can enable language-sensitive date and time formatting. The proposed dateStyle and ** timeStyle** options allow us to request a locale-specific date and time of a given length.

// Time with short format let. 
let time = new Intl.DateTimeFormat('en' , { timeStyle: 'short' });
console.log(time .format(Date.now())); // 09:27 PM 

// Time with medium format.
let time = new Intl.DateTimeFormat('en' , { timeStyle: 'medium'});
console.log(time .format(Date.now())); //09:27:50 PM 

// Time with long format. 
let time = new Intl.DateTimeFormat('en' , { timeStyle: 'long' }) ;
console.log(time .format(Date.now())); // 11:27:50 PM GMT+11
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this article, I discussed the top eight highlights of the ES2021 update. I hope this article helped you to improve your JavaScript knowledge. Thank you for reading.

Syncfusion Essential JS 2 is the only suite you will ever need to build an app. It contains over 65 high-performance, lightweight, modular, and responsive UI components in a single package. Download a free trial to evaluate the controls today.

If you have any questions or comments, you can also contact us through our support forums, support portal, or feedback portal. We are always happy to assist you!

Related blogs

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .