In this article, we’re going to review some of the latest and greatest features coming with ES2020. 🔥
🤠 Getting started
We are going to test these features in a Node.js environment using Babel.
Method #1: creating a project from scratch
Start by creating a new project:
$ mkdir es2020-tests $ yarn init Now add @babel/cli @babel/core @babel/node @babel/preset-env dependencies:
$ yarn add --dev @babel/cli @babel/core @babel/node @babel/preset-env Create a .babelrc file:
{ "presets": ["@babel/preset-env"] } Method #2: clone the source code repository
You can also clone the following GitHub repository that includes the setup and source code of the examples in this article.
$ git clone git@github.com:olivierloverde/es2020-examples.git $ yarn install 🤖 The ES2020 features
Private variable in Class
You can now declare a private variable in a class by using a hastag #. If a private variable is called outside of its class It will throw a SyntaxError.
class MyClass { #privateVariable = "Hello private world" helloWorld() { console.info(this.#privateVariable) } } const myClass = new MyClass() myClass.helloWorld() // works console.info(myClass.#privateVariable) // SyntaxError: Private field '#privateVariable' must be declared in an enclosing class BigInt
There was a limitation on largest possible integer because of how Javascript represented number internally (it is using a 64-bit floating point, see IEE 754.
const maxInteger = Number.MAX_SAFE_INTEGER; console.info(maxInteger); // 9007199254740991 console.info(maxInteger + 1); // 9007199254740992 console.info(maxInteger + 2); // 9007199254740992 ?? console.info(maxInteger + 3); // 9007199254740994 console.info(maxInteger + 200); // 9007199254741192 ?? console.info(maxInteger * 200); // 1801439850948198100 ?? Now there is a native solution, BigInt is a built-in object that provides a way to represent whole numbers larger than 2⁵³ — 1, which is the largest number in JS number).
You can create a BigInt by:
- creating a
BigIntobject:const value = BigInt(500) - appending a
nto a number:const value = 500n
For the moment, it cannot be used with methods in the built-in Math object and cannot be operated with Number. Bitwise operators are supported except >>> because all BigInts are signed.
// Using BigInt const maxIntegerBigInt = BigInt(maxInteger); console.info(maxIntegerBigInt); // 9007199254740991n console.info(maxIntegerBigInt + 1n); // 9007199254740992n console.info(maxIntegerBigInt + 2n); // 9007199254740993n console.info(maxIntegerBigInt + 3n); // 9007199254740994n console.info(maxIntegerBigInt + 200n); // 9007199254741191n console.info(maxIntegerBigInt * 200n); // 1801439850948198200n Promise.allSettled()
Promise.allSettled takes an array of Promise object as argument and waits that all promises settle to return the corresponding result as an array of objects {status, ?value, ?reason}.
const resolvingPromise1000ms = new Promise((resolve, reject) => setTimeout(resolve, 1000)); const rejectingPromise2000ms = new Promise((resolve, reject) => setTimeout(reject, 2000)); const timeCheckpoint = Date.now(); Promise.allSettled([ resolvingPromise1000ms, rejectingPromise2000ms ]).then(data => { const elapsedTimeInMS = Date.now() - timeCheckpoint; console.info(`Promise.allSettled resolved after ${elapsedTimeInMS}ms`) console.info(data) }); /* Promise.allSettled resolved after 2006ms // ? not sure why we have 6ms [ { status: 'fulfilled', value: undefined }, { status: 'rejected', reason: undefined } ] */ Nullish Coalescing Operator
When you use || operator, it returns the first argument to be true. However, sometimes you a default value considered as false such as 0 or "". To avoid it we can use the nullish coalescing operator ?? like below:
let object = { car: { speed: 0, name: "" } }; console.info(object.car.speed || 90); // 90 console.info(object.car.speed ?? 90); // 0 console.info(null || true); // true console.info(null ?? true); // true console.info(undefined || true); // true console.info(undefined ?? true); // true console.info(0 || true); // true console.info(0 ?? true); // 0 console.info("" || true); // true console.info("" ?? true); // "" console.info([] || true); // [] console.info([] ?? true); // [] console.info({} || true); // {} console.info({} ?? true); // {} console.info(true || "hey"); // true console.info(true ?? "hey"); // true console.info(false || true); // true console.info(false ?? true); // false Optional Chaining Operator
Let's take the following object as an example:
let person = { name: "John", age: 20 }; Let's say we want to access a property on this object that we are not sure to have, we usually do:
if (person.city !== undefined && person.city.locale !== undefined) { const cityLocale = person.city.locale; } This ensures the program does not throw any "error cannot read property name of undefined".
Now with the optional chaining operator, we can be more concise:
console.info(person?.city?.locale); Dynamic Import
Dynamic import() returns a promise for the module namespace object of the requested module. Thus, we can now use the import() function with the await keyword and assign the module namespace object to a variable dynamically.
const print = (value) => console.info(value); export { print }; const doPrint = async (value) => { const Print = await import('./print.js'); Print.print(value) }; doPrint('Dynamic import works !'); String.prototype.matchAll
String.prototype.match gives an array of all matches between a string and a regexp.
For example:
const re = /(Mister )\w+/g; const str = 'Mister Smith with Mister Galladon'; const matches = str.matchAll(re); console.info(matches); // Object [RegExp String Iterator] {} console.info(Array.from(matches)); /* [ [ 'Mister Smith', 'Mister ', index: 0, input: 'Mister Smith with Mister Galladon', groups: undefined ], [ 'Mister Galladon', 'Mister ', index: 18, input: 'Mister Smith with Mister Galladon', groups: undefined ] ] */ You are now ready to use these new ES2020 features! Please leave me comment if you've liked it! 🙌
This article was originally posted on my blog olivier.codes - https://olivier.codes/2020/04/12/ES2020-Summary-of-new-features-with-examples/
Top comments (6)
That's the same as
new String()andnew Number(), in the sense that people shouldn't do this.The example below correctly does
const value = BigInt(maxInteger), a conversion call likeBoolean(Number('0')).But the description uses
new, pls fix.Good catch ! You are correct, we should not use
newwith BigInt. I've updated the article accordingly. Thank you!Thanks for share! Useful information 😍
On the first example you are accessing an undefined instance property, it should be myClass.#privateVariable instead of myClass.#helloWorld
Thanks very much for catching this typo! I've updated the article and the source code accordingly. 🤠
You're welcome :)