JavaScript ES2021 - You Need To See These ES12 Features

JavaScript ES2021 - You Need To See These ES12 Features

About the author

@catalinmpit is a software engineer, AWS community builder and technical writer based out of London. He’s currently an engineer at TypingDNA, working on applying keystroke dynamics as a means of biometrics authentication.

Check out more of his work on


It’s important to start the article by mentioning that ES2021 or ES12 is in stage 4 of the process. That means it’s not released yet. ES12 is planned to be released in June 2021. Despite that, we can have a look at the new features that are planned to be released.

What’s new in ES12?

  • String.prototype.replaceAll()
  • Promise.any
  • WeakRef
  • &&=, ||= and ??=
  • Numeric separators

Numeric Separators

Working with large numbers can quickly become confusing. For instance, consider the number “92145723”. You have to pay close attention to see that it’s 92 million and something.

With the new addition from ES2021, you can re-write the same number as follows “92_145_723”. That is, you use underscores to improve the readability. You can see it’s already better, and easier to understand the number. Now, you can clearly see it’s 92 million and something.

Therefore, the numeric separator feature is simply for improving readability. It does not affect the performance of your application negatively or positively.

// previous syntax before ES12
const number = 92145723;

// new syntax coming with ES12
const number = 92_145_723;


The new method replaceAll does not bring groundbreaking changes, but it’s a small, nice addition. As the name implies, using the method, you can replace all the occurrences from a String.

It’s always easier with an example, so let’s see the method in action:

// replacing all occurrences of x with a
// jxvxscript becomes javascript
'jxvxscript'.replaceAll('x', 'a');

Before replaceAll, you would have to use RegEx to replace all the character/word occurrences. Thus, it’s a welcome addition that allows you to replace text easier and quicker.

Logical Assignment Operators

With the new logical assignment operators - &&=, ||= and ??= - you can assign a value to a variable based on a logical operation. That is, it combines the logical operators with the assignment expression.

Think of them as similar to the +=, -=, *= and /= operators. Do not worry; it will make more sense once you see some examples for each operator.

And and equals (&&=)

The and and equals operator performs the assignment only when the left operand is truthy. Let’s see an example:

let first = 10;
let second = 15;

first &&= second;

The equivalent of the above expression is first && (first = second). If it’s hard to grasp the operator, think of it as follows:

let first = 10;
let second = 15;

if (first) {
    first = second;

The above code shows how you do the same thing before ES2021. Let’s go more in-depth and see what first &&= second means:

  • if first is truthy, then the variable second is assigned to first.
  • otherwise, if first is falsy (false, 0, -0, 0n, “”, null, undefined and NaN), then it does not do anything - second is not assigned to first.

Or or equals (||=)

On the opposite spectrum of &&=, the logical OR performs the assignment only when the left operand is falsy. As usual, let’s see an example:

let first = null;
let second = 15;

first ||= second; // first is 15 now

The equivalent of the above expression is first || (first = second). This means that the variable first gets assigned second only when first is a falsy value. If the variable first is truthy, the assignment is not performed.

After running the code, the variable first will be assigned the number “15”. If you replace let first = null with let first = 10, then the assignment does not happen. The variable first remains “10”.

The equivalent code with an “if statement” is as follows:

let first = null;
let second = 15;

if (!first) {
    first = second;

Question question equals (??=)

Similarly to the Nullish Coalescing Operator, an assignment is performed only when the left operand is nullish or undefined.

let first = null;
let second = 15;

first ??= second;

first ?? (first = second) is the equivalent of the above expression. The variable first gets assigned the variable second only if first is “null” or “undefined”. In this example, first is 15. If we replace let first = null with let first = 20, the assignment does not happen. The variable first stays “20”.

The equivalent code with an “if statement” is as follows:

let first = null;
let second = 15;

if (first == null || first == undefined) {
    first = second;

With this operator, it’s important to note that it does not check for other falsy values. It only checks for null and undefined, like the Nullish Coalescing Operator. With that being said, whenever you struggle with these operators, look at the alternative code with an “if statement”. After you use them for a while, you will get used to them.


We have a new Promise method - Promise.any(). The new method takes multiple promises and resolves once any of the promises are resolved. Promise.any() takes whichever promise resolves first. Hence its name - any.

try {
    const firstPromiseResolved = Promise.any(promisesArray);

    // do more work with the first promise resolved
catch(e) {
   // catch the error

On the other side, if no promise resolves, Promise.any() throws an AggregateError exception. It also tells the reason for the rejection if all the promises are rejected. That’s all it is about Promise.any; feel free to play with it!


WeakRef is the shorthand for Weak References, and its primary use is to hold a weak reference to another object. That means it does not prevent the garbage collector from collecting the object. The Weak Reference is useful when we do not want to keep the object in the memory forever.

But why do we need the WeakRef in the first place? In JavaScript, the object is not collected by the garbage collector as long as a reference to that object exists. Thus, it keeps the object in the memory, which leaves you with less memory. The WeakRef implementation allows you to avoid that.

You can create a Weak Reference by using new WeakRef, and you can read a reference by calling the deref() method. A simple example would be:

const largeObject = new WeakRef({
     name: "CacheMechanism",
     type: "Cache",
     implementation: "WeakRef"


Mind you, this example is just for illustrative purposes showing how to access and read weak references.

Be careful when using them. Even though the WeakRef can be useful in some cases, the TC39 Proposal advises to avoid it if possible. You can read here why you should avoid it if possible.


These are a some of the new features coming to JavaScript with ES12. For more information, keep an eye on the ECMAScript finished proposals.

Catalin regularly posts helpful development tips and guides on Twitter. Be sure to follow him at @catalinmpit

About PullRequest

HackerOne PullRequest is a platform for code review, built for teams of all sizes. We have a network of expert engineers enhanced by AI, to help you ship secure code, faster.

Learn more about PullRequest

Catalin Pit headshot
by Catalin Pit

January 18, 2021