What's new in ES2021 or ES12?
Published: 2022-01-17 15:54:39

---
title: What's new in ES2021 or ES12?
published: true
date: 2021-11-28 20:16:00 UTC
tags: 
canonical_url: https://kevinlangleyjr.dev/blog/whats-new-in-es2021-or-es12
---

As I explain in my [Modern JS with ES6+](https://kevinlangleyjr.dev/blog/modern-js#tc39) post, the [TC39](https://tc39.es/) is the group that is responsible for advancing the ECMAScript specifications and standardizing these specifications for the JavaScript language. Ever since the 2015 release of ES2015 or ES6, we've had a yearly release cycle for the next version of ECMAScript. Before a feature can be added to a release, it must first go through four proposal stages before finally being approved for release. Here we'll be looking at the features that were added in ES2021 or ES12.

You can check out all of the finished proposals, from across the years, on [GitHub](https://github.com/tc39/proposals/blob/master/finished-proposals.md).

## [`String.prototype.replaceAll`](https://github.com/tc39/proposal-string-replaceall)

```js
replaceAll(regExp, replacementString);

replaceAll(regExp, replacerFunction);

replaceAll(substr, replacementString)

replaceAll(substr, replacerFunction)
```


The `.replaceAll()` method is very similar to the `.replace()` method, but the latter will replace only the first instance and the former replaces all occurrences of a regular express or substring. This method can accept either a substring or a regular express for the first parameter and either the replacement string or a replacer function that returns a string for the second parameter. It's important to note that if the first argument of a `replaceAll()` call is a RegExp object or regular expression literal, and the second parameter is a function, the function will be invoked multiple times. For more information, like what parameters a replacerFunction has passed into it, check out the [MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll#specifying_a_function_as_a_parameter).

```js
const str = 'James lives in Central Florida. James has a dog named d00d.';

const strReplaced = str.replace( 'James', 'Kevin' ); // Kevin lives in Central Florida. James has a dog named d00d.

const strAllReplaced = str.replaceAll( 'James', 'Kevin' ); // Kevin lives in Central Florida. Kevin has a dog named d00d.
```

## [`Promise.any`](https://github.com/tc39/proposal-promise-any)

```js
Promise.any(iterable);
```

The `Promise.any()` method accepts an iterable of `Promise` objects as it's only parameter and will return a single `Promise` objet that resolves when any of the passed in `Promise` objects resolve, with the value of the resolved original `Promise` object.

```js
const promise1 = new Promise( resolve => setTimeout( resolve, 100, 'first' ) );

const promise2 = new Promise( resolve => setTimeout( resolve, 300, 'second' ) );

const promise3 = new Promise( resolve => setTimeout( resolve, 700, 'third' ) );

Promise.any( [
 promise1,
 promise2,
 promise3,
] ).then( value => console.log( value ) );
```

## [WeakRefs](https://github.com/tc39/proposal-weakrefs)

WeakRefs allow you to create a reference to an object while not preventing garbage collection from removing it later. References to objects are strongly held in JavaScript, which means that as long you have a reference to the object, it won’t be garbage-collected. WeakRefs are a way of creating a reference that is _not_ strongly held and can be garbage-collected.

According to the proposal itself, the correct use of `WeakRef` and `FinalizationRegistry` take careful thought, and they are best [avoided, if possible](https://github.com/tc39/proposal-weakrefs#a-note-of-caution). This is because they rely heavily on the garbage collection that takes place in the language. As a brief and nowhere near expansive explanation of it, JavaScript is a garbage collected language which means that if a variable is no longer reachable, the garbage collector will automatically remove it from memory. The hard part here is that the when and how garbage collection takes place is entirely up to the JavaScript engine itself. The different engines will more than likely produce different results on when or how the garbage collection takes place.

The concept is pretty simple but the use case is very rare, specific, and advanced and since these are power-user features, most usage will take place within frameworks or libraries.

A WeakRef is created with the new WeakRef constructor, and the value of the WeakRef variable can be accessed via the deRef method.

```js
const wr = new WeakRef( {
 name: 'Kevin'
} );

console.log( wr.deref()?.name );

//output: Kevin
```

You can force clear the garbage collector in Chrome within the Performance tab of the dev tools.

<img alt="Force JavaScript garbage collection in Chrome" src="https://res.cloudinary.com/kevinlangleyjr-dev/image/upload/v1637687738/blog/whats-new-in-es2021-or-es12/garbage-collection_jc1zbi.png">

## [Logical Assignment Operators](https://github.com/tc39/proposal-logical-assignment)

The purpose of this proposal was essentially to combine logical operators (`&&`, `||` or `??`) and assignment expressions.

### Logical OR assignment operator ||=

```js
x ||= y;
```

The logical OR assignment operator, `||=`, is a short-circuit evaluation just like the logical OR operator (`||`), which means that the second operand is only evaluated if the first operand is evaluated as falsy. The syntax expression above is the same as `x || (x = y)` and not `x = x || y`, where the latter always performs the assignment. This means that `y` will _only_ be assigned to `x` if `x` is falsy, otherwise, `x` retains its original value.


```js
const updateVoteCount = user => {
  // We can do this.
  if ( ! user.votes ) {
    user.votes = 1
  }

  // Or this.
  user.votes = user.votes || 1;

  // Or use the new logical assignment operator.
  user.votes ||= 1
}
```

### Logical AND assignment operator &&=

```js
x &&= y;
```

The logical AND assignment operator, `&&=` is also a short-circuit evaluation just like the logical AND operator (`&&`), which means that the second operand is only evaluated if the first operand is evaluated as truthy. The syntax expression above is the same as `x && (x = y)` and not `x = x && y`, where the latter always performs the assignment. This means that `y` will _only_ be assigned to `x` if `x` evaluates as truthy, otherwise, `x` retains its original falsy value.

```js
let x = 1;
const y = 2;

x &&= y;

console.log( x ); // 2
```

### Logical nullish assignment operator ??=

```js
x ??= y;
```

The logical nullish assignment operator, `??=` is also a short-circuit evaluation just like the logical nullish operator (`??`), which means that the second operand is only evaluated if the first operand is evaluated as `null` or `undefined`. The syntax expression above is the same as `x ?? (x = y )` and not `x = x ?? y`, where the latter always performs the assignment. This means that `y` will _only_ be assigned to `x` if `x` evaluates as `null` or `undefined`, otherwise, `x` retains it's original value.

```js
const getKey = () => 'test-key';

const user = { name: 'Kevin', age: 33 };

user.key ??= getKey();

console.log( user.key ); // 'test-key'
```

## [Numeric separators](https://github.com/tc39/proposal-numeric-separator)

Is `1000000000` a million, a billion, or somewhere in between? With the new numeric separator you can more easily determine the actual value of Numbers and BigInts by allowing the numbers to be separated by `_` to separate number groups.

```js
let num = 1_000_000_000; /// 1 billion.

num = 1_000_000; // 1 millon.

num = 100_000_000; // 100 millon.
```