- Published on
What's New in JavaScript ES2021?
- Authors
- Name
- Justin Kelly
- @JustinHKelly
This post is a collection of all the latest features added to JavaScript as part of the ES2021 Spec.
ES2021
proposal📘
String.prototype.replaceAll -This new method provides a more straight-forward way to replace all occurences of a matching substring in a string without using regex or array methods.
The most common approach for doing this is using a regex expression with the replace
method:
const animals = 'dinosaurs+dogs+cats+alligators';const withSpaces = animals.replace(/\+/g, ' ');
And the regex-free aproach uses split
& join
:
const animals = 'dinosaurs+dogs+cats+alligators';const withSpaces = animals.split('+').join(' ');
The new approach is to use replaceAll
. No regex, no unnecessary converting back and forth from arrays.
const animals = 'dinosaurs+dogs+cats+alligators';const withSpaces = animals.replaceAll('+', ' ');
proposal📘
Promise.anyPromise.any
accepts an iterable of promises and returns a promise that is
fulfilled by the first given promise to be fulfilled, or rejected with
an AggregateError
holding the rejection reasons if all of the given promises are rejected.
(If something more fundamental goes wrong, e.g. iterating over the iterable results in an exception, Promise.any
returns a rejected promise with that exception.)
Example
const promiseWithError = new Promise((resolve, reject) => { reject('Always fails');});
const promiseSlow = new Promise((resolve, reject) => { setTimeout(resolve, 600, 'Done eventually.');});
const promiseMedium = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'Done pretty fast.');});
const promiseFast = new Promise((resolve, reject) => { setTimeout(resolve, 10, 'Done first!');});
Promise.any([ promiseWithError, promiseSlow, promiseMedium, promiseFast,]).then((value) => { console.log(value); // promiseFast fulfils first});// output: "Done first!"
proposal📘
WeakRefsThe primary use case for weak references is to create caches or mappings to large objects.
According to the proposal: "it's best if WeakRef
objects and FinalizationRegistry
objects are used as a
way to avoid excess memory usage, or as a backstop against certain bugs, rather
than as a normal way to clean up external resources or observe what's allocated."
In other words, don't use these new features unless you are really sure you know what you're doing.
Let's look at an example:
const callback = () => { const hugeObject = new WeakRef({ name: 'A Huge Object v2.0', }); console.log(hugeObject.deref().name);};
const promise1 = new Promise((resolve) => { setTimeout(() => { callback(); // Will log "A Huge Object v2.0" resolve(); }, 2000);});
const promise2 = await new Promise((resolve) => { setTimeout(() => { callback(); // No guarantee "A Huge Object v2.0" will be logged resolve(); }, 50000);});
Promise.all([promise1, promise2]);
proposal📘
Logical Assignment OperatorsThis new feature combines the logical operations(&&
, ||
& ??
) with assignment (=
) into three new operators:
&&=
, ||=
& ??=
.
So now instead of writing this:
let x = 0;let y = 2;if (x) { x = y;}console.log(x); // prints 2
Or this:
let x = 0;let y = 2;x && (x = y);console.log(x); // prints 2
We can just write:
let x = 0;var y = 2;x &&= y;console.log(x); // prints 2
let a;let b = a ?? 4;console.log(b); // 4
// This can be simplified to this
let c;let d = 4;c ??= d;console.log(c); // 4
proposal📘
Numeric separatorsOne of the simplest additions to the ES2021 spec is underscores (_
) as a numeric separator.
The primary purpose of this is to make code more readble. What is "10000000000", one billion, or ten billion? Using the _
to break up values makes them much easier to read.
const trillion = 1_000_000_000_000; // Instantly readable as opposed to 1000000000000const tenBillion = 10_000_000_000;const twentyDollarsInCents = 20_00; // It's obvious that 2000 here refers to 20 dollars and 0 cents