Sambat Lim Blog

moon indicating dark mode
sun indicating light mode

What new in ES2021 (aka ES12)?

November 05, 2020


Last year, I wrote a blog to summarize the brief history of javascript from ES6 to ES11. If you didn’t read it yet, you can check out here.

Every year, javascript got the new update. ECMAScript 2021(ES2021) version is expected to be released in the month of June 2021.

List down below is some new updates of ES2021 (aka ES12) that have been proposed in ECMAScript proposal (final stage):

Some of the codes and examples, I got it from:


String replaceAll() Method

With this new update, we are able to replaceAll the string with the new string using string.replaceAll() method.

Old approach

// in the previous version
let string = 'The dog is eating dogfood.';
let newString = string.replace('dog','cat');
// output: The cat is eating dogfood.
// To replace all the word dog with cat, we need to use regular expression.
let string = 'The dog is eating dogfood.';
let newString = string.replace(/dog/g,'cat');
// output: The cat is eating catfood.

New approach

// with the new update, we can use method replaceAll()
let string = 'The dog is eating dogfood.';
let newString = string.replaceAll('dog','cat');
// output: The cat is eating catfood.

Private Methods

Private method is accessible only in its own class. Private method start with #.

class Car {
// Private method
#carColor() {
console.log("The car is white.");
// Public method
showCarColor() {
const carObj = new Car();
carObj.showCarColor(); // "The car is white.";
carObj.carColor(); // TypeError: carObj.carColor is not a function

Private Accessors

Private Accessors function start with #.

class Car {
// Public accessor
get name() { return 'Honda' }
set name(value) {}
// Private accessor
get #color() { return 'red' }
set #color(value) {}

We can access the Accessors as belows:

const carObj = new Car();
console.log(; // "Honda"
console.log(carObj.color); // undefined

Logical Operators and Assignment Expressions

Logical assignment operator combines the logical operations(&&, || or ??) with assignment.


let a = 1;
let b = 2;
a ||= b;
// equivalent to a = a || b
console.log(a); // output: 1
let c = 2;
let d = 5;
c &&= d;
// equivalent to c = c && d
console.log(c); // output: 5
let e;
let f = 2;
e ??= f;
// equivalent to e = e ?? f
console.log(e) // output: 2

Let’s see the summarize below:

  • a ||= b will return a if a is a truthy value, or b if a is falsy
  • c &&= d will return d if both c and d are truthy, or c otherwise
  • e ??= f will returnf if e is null or undefined otherwise it will return e

Read More

WeakRef and Finalizers


WeakRef stands for Weak References. Main use of weak references is to implement caches or mappings to large objects. For example: we don’t want to keep a lot of memory for the rarely used cached or mapping so we can allow memory to be garbage collected and generate the fresh one if we need it.

Read More about javascript garbage collection here.


To create WeakRef we just simply use new WeakRef and to call the weakref we can use .deref().

const callback = () => {
const aBigObj = new WeakRef({
name: "Backbencher"
(async function(){
await new Promise((resolve) => {
setTimeout(() => {
callback(); // Guaranteed to print "Backbencher"
}, 2000);
await new Promise((resolve) => {
setTimeout(() => {
callback(); // No Gaurantee that "Backbencher" is printed
}, 5000);

As you can see the code above the second await cannot Gaurantee the word “Backbencher” is printed which means it is already garbage collected.

Please make sure you use weakref only on the big obj that isn’t so important for your program to run.


FinalizationRegistry is a companion feature of WeakRef. It lets programmers register callbacks to be invoked after an object is garbage collected.

const registry = new FinalizationRegistry((value) => {

Here registry is an instance of FinalizationRegistry. The callback function passed to FinalizationRegistry gets triggered when an object is garbage collected.

(function () {
const obj = {};
registry.register(obj, "Backbencher");
// this will passed the value "Backbencher" to registry when obj is garbage collected.
// and will print "Backbencher" as the output.

Promise.any() and AggregateError

Promise.any() resolves if any of the supplied promises is resolved. Below we have 3 promises, which resolves at random times.

const p1 = new Promise((resolve, reject) => {
setTimeout(() => resolve("A"), Math.floor(Math.random() * 1000));
const p2 = new Promise((resolve, reject) => {
setTimeout(() => resolve("B"), Math.floor(Math.random() * 1000));
const p3 = new Promise((resolve, reject) => {
setTimeout(() => resolve("C"), Math.floor(Math.random() * 1000));

Out of p1, p2 and p3, whichever resolves first is taken by Promise.any().

(async function() {
const result = await Promise.any([p1, p2, p3]);
console.log(result); // Prints "A", "B" or "C"

What if none of the promises resolve? In that case Promise.any() throws an AggregateError exception. We need to catch it and handle it.

const p = new Promise((resolve, reject) => reject());
try {
(async function() {
const result = await Promise.any([p]);
} catch(error) {

Read More

Numeric Separators

The introduction of Numeric Separators will make it easier to read numeric values by using the _ (underscore) character to provide a separation between groups of digits.

Let’s look at more examples:

1_000_000_000 // Ah, so a billion
101_475_938.38 // And this is hundreds of millions
let fee = 123_00; // $123 (12300 cents, apparently)
let fee = 12_300; // $12,300 (woah, that fee!)
let amount = 12345_00; // 12,345 (1234500 cents, apparently)
let amount = 123_4500; // 123.45 (4-fixed financial)
let amount = 1_234_500; // 1,234,500

Read More


The Intl.ListFormat object is a constructor for objects that enable language-sensitive list formatting.

The following example shows how to create a formatted list using the English language.

// Create a list formatter in your locale
// with default values explicitly passed in.
const lf = new Intl.ListFormat("en", {
localeMatcher: "best fit", // other values: "lookup"
type: "conjunction", // "conjunction", "disjunction" or "unit"
style: "long", // other values: "short" or "narrow"
lf.format(['Motorcycle', 'Truck' , 'Car']);
// > "Motorcycle, Truck, and Car"

You are not limited to English, let’s try with a few different languages:

const list = ['Apple', 'Orange', 'Banana'];
// Italian
console.log(new Intl.ListFormat('it', { style: 'long', type: 'conjunction' }).format(list));
// Apple, Orange e Banana
// Spanish
console.log(new Intl.ListFormat('es', { style: 'long', type: 'conjunction' }).format(list));
// Apple, Orange y Banana
// German
console.log(new Intl.ListFormat('de', { style: 'long', type: 'conjunction' }).format(list));
// Apple, Orange und Banana

Read More

dateStyle and timeStyle options for Intl.DateTimeFormat

We can use dateStyle and timeStyle to request a locale-specific date and time of a given length.

// short
new Intl.DateTimeFormat("en" , {
timeStyle: "short"
// "2:45 PM"
// medium
new Intl.DateTimeFormat("en" , {
timeStyle: "medium"
// "2:45:53 PM"
// long
new Intl.DateTimeFormat("en" , {
timeStyle: "long"
// "2:46:05 PM GMT+7"

Now let’s try with dateStyle:

// short
new Intl.DateTimeFormat("en" , {
dateStyle: "short"
// "7/25/20"
// medium
new Intl.DateTimeFormat("en" , {
dateStyle: "medium"
// "Jul 25, 2020"
// long
new Intl.DateTimeFormat("en" , {
dateStyle: "long"

Read More

🎉🎉That's all for **What's New in Javascript ES2021**! See you next year...🎉🎉

Welcome to Sambat Blog.
I blog about web development and design.