JavaScript new features in ECMAScript 2021
Tags: javascript, ecmascript, react
Published: 2021-06-01 07:23:57

Below are some new features that you can expect from the ECMAScript:
* **replaceAll**
* **Promise.any**
* **WeakRefs and finalizer**
* **Logical Assignment Operators**
* **Numeric separator**

Let's begin with the first one.


###1. replaceAll() method

The **replaceAll()** method allows you to replace all occurrences of a substring with another string that you defined. Currently, the **replace()** method only replace the first occurrence of the substring while ignoring the rest:
```
const str = 'How+are+you?';
const addSpaces = str.replace('+', ' ');
console.log(addSpaces); // How are+you?
```
The only way to replace all occurrences is to use **replace()** with a global regular expression as follows:
`// replace all '+' with a 'space'`
```
const str = 'How+are+you?';
const addSpaces = str.replace(/\+/g, ' ');
console.log(addSpaces); // How are you?
```
With the **replaceAll()** method, you don’t have to use a regular expression anymore:
```
const str = 'How+are+you?';
const addSpaces = str.replaceAll('+', ' ');
console.log(addSpaces) //How are you?
```


###2. Promise.any()


The **Promise.any()** method returns a promise that will resolve as soon as one of the promises are resolved. If all of the promises are rejected, the method will throw an AggregateError exception holding the rejection reasons.
Here’s an example:

```
const firstPromise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("First Promise Fulfilled"), 3000);
});
const secondPromise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("Second Promise Fulfilled"), 2000);
});
const thirdPromise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("Third Promise Fulfilled"), 1000);
});
Promise.any([firstPromise, secondPromise, thirdPromise]).then(
  (promiseFulfilled) => {
    // Any of the promises was fulfilled.
    console.log(promiseFulfilled); // Third Promise Fulfilled
  },
  (error) => {
    console.log(error)// Error Handling
  }
);

```

If all of the promises given are rejected, the AggregateError exception will be thrown.
Here’s another example showing the exception using the async/await syntax:
```
const firstPromise = new Promise((resolve, reject) => {
  setTimeout(() => reject(), 1000);
});
try {
  const first = await Promise.any([firstPromise]);
  // Any of the promises was fulfilled.
} catch (error) {
  console.log(error);
  // AggregateError: All promises were rejected
}
```


###3. WeakRefs

The **WeakRef**, which stands for **Weak References**, allows you to create a weak reference to an object. The primary use of Weak Reference is to implement caches or mappings of a large object.
A regular/ strong JavaScript object reference will never be claimed by the garbage collector. A weak reference to an object, in contrast, can be claimed by JavaScript garbage collector:
`const simpleObj = {name: "John Doe"};
const referenceObj = new WeakRef({name: "John Doe"});`
When you need to read the value of WeakRefs , you need to use the **deref()** method to return the instance’s target object:

```
const referenceObj = new WeakRef({name: "John Doe"});
const obj = referenceObj.deref();
console.log(obj.name); // John Doe
```

Because the implementation detail of when, how, and whether JavaScript garbage collection actually occurs or not is up to the JavaScript engine implementation, you may observe different behavior between one JavaScript environment and another.
The correct use of **WeakRef** takes careful thought, and it’s best to avoid implementing one if possible. Unless you’re a JavaScript library maintainer, you will most likely never need to use it.

###4. Finalizers

The **Finalizer** is a companion feature of WeakRef that allows you to execute a piece of code after an object has become unreachable to the program.
In short, you can register a callback function that gets triggered after the garbage collection occurs. You can create a registry by passing the callback to the **FinalizationRegistry** object:

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

Then, you can register any object you want to cleanup for by calling the register() method, passing both the object and the value you want to pass to the callback function:
`registry.register({name: "John"}, "any value");`
The object passed into the register() method will be weak-referenced so that it can be garbage collected. Based on the code above, the callback will log “any value” to the console.
Both WeakRefs and Finalizers are tricky concepts. You can learn more about weak reference and FinalizationRegistry. 
[WeakRef](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef)
[FinalizationRegistry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry)



###5. Logical assignment operator

*  ||= [Logical OR assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_OR_assignment)
*  &&= [Logical AND assignment ](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND_assignment)
*  ??= [Logical nullish assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_nullish_assignment)

The logical assignment operator combines Logical Operators and Assignment Expressions, allowing you to write a shorter syntax for variable value checking.


For example, the following code checks whether the value of x is falsy and only assign a new value when it is:

```
let x;
if(!x){
  x = 7;
}
```

Using the logical assignment operator, you can replace the above code with the following:
```
let x;
**x ||= 11;** // since x is undefined, it's assigned the number 11
console.log(x); // 11
The logical assignment works with logical AND (**&&**) and nullish coalescing operator (**??**) as well:
let x = null;
x ??= 11 // assign 11 to x when it's null or undefined
let y = "JavaScript";
y &&= 11 // assign 11 to y when it's value is truthy

```



###6. Numeric separator

The numeric separator proposal helps you to write more readable code by allowing you to use underscore (**_**) as a separator when you define a numeric value.
The following code shows the comparison between a normal number and a separated number for one million:
```

const oneMillion = 1000000;
const separatedOneMillion = 1_000_000;
console.log(separatedOneMillion); //1000000

```
As you can see, separating the number with an underscore makes it much more readable. You can even use it on numbers with floating points as follows:
```
const randomFloat = 4.11_857_111_1211;
console.log(randomFloat) //4.118571111211
```
The separator won’t be included when you use the value for operations:
```
const randomFloat = 4.7_857_123;
console.log(randomFloat); // 4.7857123
```
####Imported Note that you can only use the separator between two digits:####
```
const num = 4_111; // 4111
// All the below throws an error
const a = 47_; //Uncaught SyntaxError: Numeric separators are not allowed at the end of numeric literals
const b = _11;//Uncaught ReferenceError: _47 is not defined
const c= 7._11;Uncaught SyntaxError: Invalid or unexpected token
```