A new year, a new ECMAScript! Last year 8 proposals have reached stage 4, and are now included in the release of ES2020. In this post, I'll discuss 5 of these new additions using code examples. But first, let's have a quick look at what the process of adding a new addition to ECMAScript looks like.
The ECMAScript Process
At the very core of the specification is TC39, the committee that evolves JavaScript, adds and reviews new proposals to ECMAScript. Proposals to the specification usually represent problems that the committee (and community) is interested in exploring solutions for. New additions have to go through five stages in which their value and feasibility are tested, before being added to ECMAScript:
Stage 0: Strawperson: TC39 members can propose any idea, change, or addition that hasn't been proposed before (or wasn't completely rejected).
Stage 1: Proposal: A proposal is created by a TC39 member, and discusses a concrete problem and solution.
Stage 2: Draft — The syntax (most of) and semantics of the proposal are described using the formal specification language.
Stage 3: Candidate — Specifications for the proposal are completed and reviewers have signed-off on these.
Stage 4: Finished — The proposal is ready to be included in an upcoming ECMAScript release.
In 2019 some proposals made it to stage 4, including the 5 new additions listed in the next section!
Finished Proposals
As mentioned before, a proposal is finished when it reaches stage 4. At this point the proposal is complete and the syntax and semantics match the criteria of TC39. For this post I've selected 5 of these proposals that interested me the most:
1. Optional Chaining (Github)
This is probably the proposal that got the most attention of all proposals on this list. Optional chaining helps you to get rid of writing code to validate if you're able to read values by chaining. Instead of throwing an error when you use the chaining operator .
to reach a value that doesn't exist, the optional chaining operator .?
will return undefined
. Suppose you have a variable called post
with the following form:
const post = {
title: 'My post',
description: 'Lorem Ipsum...',
meta: {
title: 'My Post'
}
}
If you want to get the value for the title
field from meta
, you can use the chaining operator .
to get that value:
console.log(post.meta.title)
// My Post
But when you're not sure if the field meta
will exists, you need to add a check for that field otherwise you'll get a TypeError
when running your code:
const post = {
title: 'My post',
description: 'Lorem Ipsum...',
}
console.log(post.meta && post.meta.title)
// undefined
console.log(post.meta.title)
// Uncaught TypeError: Cannot read property 'title' of undefined
With the optional chaining parameter .?
you can leave out the validation for the existence of the field meta
like this:
console.log(post.meta?.title)
// undefined
🚀 Play with the code on CodePen
2. Dynamic import()
(Github)
Developers that use web frameworks or libraries to write applications are probably already familiar with dynamic imports. Dynamically importing modules in your application can help you with improving the performance of your application, like React.lazy
does for React applications. With the dynamic import()
statement you can also use this feature in any JavaScript application, so instead of a static import:
import { getPosts } from './utils';
console.log(getPosts());
// Array of posts
You can now dynamically import this function into your application:
import("./utils").then(utils => {
console.log(utils.getPosts());
// Array of posts
});
And even destructure the getPosts
function while doing so:
let posts = []
import("./utils").then(({ getPosts }) => {
console.log(getPosts());
// Array of posts
});
By dynamically importing code you can reduce the time that your applications take to load, and focus on returning something to the user as fast as possible.
3. Promise.allSettled
(Github)
In recent releases of ECMAScript, there have been multiple additions that improved the Promise
constructor, which are Promise.all
, Promise.race
, and Promise.any
. These methods (or also called Promise combinators) help you tying multiple Promises together, like using the Promise.all
method to combine the results of multiple Promises (or in example fetch
requests):
const promises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.resolve(3)
];
Promise.all(promises)
.then(responses => console.log(responses)) // [1, 2, 3]
.catch(e => console.log(e))
As all Promises resolve, the response will be the combined results of all Promises. The downside is that when one of your Promises rejects, the results don't get returned:
const promises = [
Promise.resolve(1),
Promise.resolve(2),
Promise.reject('error')
];
Promise.all(promises)
.then(responses => console.log(responses))
.catch(e => console.log(e)) // "error"
Instead of returning the combined results of all Promises, only the results of the rejected Promise will be returned. The Promise.allSettled
method fixes this by returning a status for all the Promises:
Promise.allSettled(promises)
.then(responses => console.log(responses.map(response => response.status))) // ["fulfilled", "fulfilled", "rejected"]
And also the values if the Promise resolved, or the reason for rejecting the Promise:
Promise.allSettled(promises)
.then(responses => console.log(responses.map(response => response.value || response.reason))) // [1, 2, "error"]
🚀 Play with the code on CodePen
4. Nullish coalescing Operator (Github)
This last addition I'd like to mention is somewhat similar to the optional chaining operator .?
, as both additions help you to skip writing code for validating values. In the case of the nullish coalescing operator ??
, it saves you time checking for values that are falsy null, like an empty string:
const post = {
title: 'My post',
description: 'Lorem Ipsum...',
meta: {
title: ''
}
}
console.log(post.meta.title || 'Not found')
// Not found
Above you can see that the value for title
in meta
is an empty string, which is seen as false
by the ||
operator. However, with the nullish coalescing operator ??
the value for metaTitle
will be the empty string:
console.log(post.meta.title ?? 'Not found')
// ''
🚀 Play with the code on CodePen
5. BigInt
(Github)
This last one might not be an addition that you'll use, but I'm pretty sure it will show up in technical interviews. With the BigInt
primitive, the biggest Number
that can be represented in JavaScript is no longer 9007199254740991. If you look at the maximum value of Number
, you'll see the following:
const maxNumber = Number.MAX_SAFE_INTEGER
console.log(maxNumber) // 9007199254740991
console.log(maxNumber + 1) // 9007199254740992
console.log(maxNumber + 2) // 9007199254740992
As 9007199254740992 is the maximum value Number
can represent in JavaScript, you can't exceed this number. However, with BigInt
you can get a higher value:
const maxNumber = Number.MAX_SAFE_INTEGER
const biggerNumber = BigInt(maxNumber) + 2n
console.log(biggerNumber) // 9007199254740993n
Notice, you can't add the value 2
to the BigInt
, instead, you need to add the value 2n
. To display the value of the BigInt
you need to use the method toString()
or toLocaleString()
, as the value can only be used for calculations
console.log(biggerNumber.toString()) // "9007199254740993"
🚀 Play with the code on CodePen
What else?
In this post, I've shared my favorite new additions to the ECMAScript specification, but more have been released in ES2020. For the full list of finished (and released) proposals, you can have a look here. Missing a new addition that you like on this list? Use the comments section or Twitter to let me know!
Photo by SpaceX on Unsplash
Top comments (1)
Nice introduce for these specs.
There is one typo:
The operator is
?.