MEMEPh. ideas that are worth sharing...

What is new in ES2021 or ES12

Foreword


On March 13, 2021, the ES2021 candidate proposal released a version of its final feature set. If it can be passed at the ECMA conference in June this year, it will become an official standard!

The new ECMAScript features mentioned in this candidate proposal are as follows:

These new features have entered the fourth phase and have been added to the Google Chrome V8 engine. Next, let's introduce these new features of ES2021.

 

String.prototype.replaceAll()


const newString = oldString.replaceAll(pattern, replacement);

This method returns a new string with all  pattern the substitutions passed to it replacement where the pattern argument can be a string or a regular expression, and the replacement argument can be a string or a function to execute for each match.

replaceAll The method is the sequel to the String.replace method, String.replace only replaces patternthe first found position.

const str = "Linda is a self-taught developer.Linda will rule the world";
let newStr = str.replace("Linda","Micheal")
//output: Micheal is a self-taught developer.Linda will rule the world
let newStr = str.replaceAll("Linda","Micheal")
//output: Micheal is a self-taught developer.Micheal will rule the world

In the past, if you needed to replace all matching items, you had to write a regular expression to perform a complete replacement.

const str = "hello world, hello code";
const newStr = str.replace(/hello/g, "hi");
console.log(newStr); // "hi world, hi code"

There is now String.prototype.replaceAll()complete replacement of matches even in the input string.

const str = "hello world, hello code";
const newStr = str.replaceAll("hello", "hi");
console.log(newStr); // "hi world, hi code"

 

Promise.any


The Promise.race() and Promise.all() added in ES2020 Promise.allSettled(). ES2021 added another method to make Promise processing easier:Promise.any()

Promise.any() Takes an Promise iterable, and as long as one of them  promise succeeds, return the one that has succeeded  promise (as in Example 1). If none of the iterables  promise succeed (i.e. all  promise fail/reject), return an instance of the failed  promise sum AggregateErrortype (as shown in example 2), which is  Error a subclass of , which is used to group a single error in Together.

Promise.any() It is very similar Promise.race()to a method, except that it does not end because a certain state Promisebecomes rejected.

// example 1
Promise.any([
new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')),
new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')),
new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),
])
.then(value => console.log(`Result1: ${value}`))
.catch(err => console.log(err))



Promise.race([
new Promise((resolve, reject) => setTimeout(reject, 200, 'Third')),
new Promise((resolve, reject) => setTimeout(resolve, 1000, 'Second')),
new Promise((resolve, reject) => setTimeout(resolve, 2000, 'First')),
])
.then(value => console.log(`Result2: ${value}`))
.catch(err => console.log(err))


/****Output****/
// Third
// Result1: Second

In the above code, Promise.any() the parameter array of the method contains three Promise operations. As long as one of them becomes fulfilled, Promise.any() the returned Promise object becomes fulfilled, and Promise.race([p1, p2, p3]) whichever result gets faster, returns that result, regardless of whether the result itself is a success state or a failure state.

Promise.any() Returns  AggregateError an error if no promise is fulfilled .

// example 2
const pErr1 = new Promise((resolve, reject) => {
reject('always fail 1');
});
const pErr2 = new Promise((resolve, reject) => {
reject('Always fail 2');
});
Promise.any([pErr1,pErr2]).catch((err) => {
console.log(err);
})

/****Output****/
// "AggregateError: All promises were rejected"

 

Logical operators and assignment expressions (&&=, ||=, ??=)


There are many assignment and logical operators in JavaScript, such as the following basic example:

// Assignment Operator Example
let num = 5
num+=10
console.log(num) // 15
// Logical Operator Example
let num1 = 6
let num2 = 3
console.log(num1 === 6 && num2 === 2) // false
console.log(num1 === 6 || num2 === 2) // true

The new proposal will allow us to combine logical operators with assignment operators

1. Logical assignment operator with && operator

var x = 1;
var y = 2;
x &&= y;
console.log(x); // 2

The operation on line 3 is equivalent to: x && (x = y)

or equivalent to

if(x) {
  x = y
}

Since x is the real value, the value y is assigned, which is 2. In short, the operator &&=assigns the value of the RHS variable to the LHS variable only if the LHS value is true.

 

2. Operators with || Logical assignment operator

The RHS variable value is assigned to the LHS variable only if the LHS value is false.

// Logical Assignment Operator with || operator
let num1
let num2 = 10
num1 ||= num2
console.log(num1) // 10
// Line 4 can also be written as following ways
// 1. num1 || (num1 = num2)
// 2. if (!num1) num1 = num2

 

3. Logical assignment operator with ?? operator

ES2020 introduced the null coalescing operator, which can also be combined with the assignment operator. The RHS variable value is assigned to the LHS variable only if LHS is undefined or simply null.

// Logical Assignment Operator with ?? operator
let num1
let num2 = 10
num1 ??= num2
console.log(num1) // 10
num1 = false
num1 ??= num2
console.log(num1) // false
// Line 4 can also be written as following ways
// num1 ?? (num1 = num2)

 

Numeric separator


We will make reading numerical values ​​easier and improve readability by using the _ (underscore) character to provide separation between groups of numbers .

let x = 100_000; // 100000

Numeric separators also work for BigInt numbers.

const trillion = 1000_000_000_000n;
console.log(trillion.toString()); // "1000000000000"

Delimiters are for readability purposes only. Therefore, it can be placed anywhere in the number.

const amount = 178_00;
console.log(amount.toString()); // "17800"

 

WeakRef and Finalizers


This feature consists of two advanced objects WeakRef and FinalizationRegistry. Depending on the use case, these interfaces can be used individually or together. **The official recommendation is not to use WeakRef and finalizer. **One reason is that they can be unpredictable, another is that they don't really do the job for the gc and may actually make garbage collection's job harder.

In JavaScript, when you create a reference that creates an object, this reference prevents the object from being garbage collected, which means JavaScript cannot delete the object and free its memory. This object can be made to exist forever as long as the reference to the object persists.

ES2021 has new classes WeakRefs. Allows creation of weak references to objects. This allows existing objects to be tracked without preventing them from being garbage collected. Very useful for caching and object mapping.

New ones must be created with the new keyword WeakRef and put some object in parentheses as parameters. When you want to read a reference (the referenced object), you can do so by calling deref() on.

const myWeakRef = new WeakRef({
name: 'Hoshino',
year: '25'
})

myWeakRef.deref()
// => { name: 'Hoshino', year: '25' }

myWeakRef.deref().name
// => 'Hoshino'

WeakRef Closely linked to is another function called finalizersor FinalizationRegistry. This feature allows you to register a callback function that will be called when the object is garbage collected.

// Create FinalizationRegistry:
const reg = new FinalizationRegistry((val) => {
console.log(val)
})

(() => {

// Create new object:
const obj = {}

//Register finalizer for "obj" object:
//First parameter: the object to register the finalizer for.
//The second parameter: the value of the callback function defined above.

 reg.register(obj, 'obj has been garbage-collected.')
})()

// output when "obj" is garbage collected:
// 'obj has been garbage-collected.'