Since ES2015, updates from the TC39 committee are released annually. Their latest release ES2020 comes with many new features.
In this article, I will discuss my favorite new features from ES2020 as listed below:
- BigInt
- Dynamic Imports
- globalThis
- Nullish Coalescing Operator
- Optional Chaining
BigInt
BigInt is a new numeric primitive in JavaScript that allows us to safely store and operate on large integers, even beyond the safe integer limit for Numbers.
This opens up countless new opportunities for mathematical operations. The variables can now represent numbers²⁵³ and not just max out at 9007199254740992.
let maxNumber = Number.MAX_SAFE_INTEGER;
console.log(maxNumber); // 9007199254740991
maxNumber = ++maxNumber;
console.log(maxNumber); // 9007199254740992
// Even though we are incrementing the number, variable value stays same
maxNumber = maxNumber++;
console.log(maxNumber); // 9007199254740992
To create a BigInt, add the ’n’ suffix to any integer literal. For example 10 becomes 10n. To convert any number to BigInt use the global function BigInt(number).
let maxNumber = Number.MAX_SAFE_INTEGER;
console.log(maxNumber); // 9007199254740991
maxNumber = maxNumber + 1;
console.log(maxNumber); // 9007199254740992
maxNumber = maxNumber + 1;
console.log(maxNumber); // 9007199254740992
maxNumber = BigInt(maxNumber) + 10n;
console.log(maxNumber); // 9007199254741002n
Dynamic Imports
Dynamic Imports is one of my favorite feature of ES2020. As the name implies, you can import modules dynamically. Using dynamic imports, the code is delivered via smaller bundles as required (instead of downloading a single large bundle as has been previously required). When using dynamic imports, the import keywords can be called as a function, which returns a promise. Below is an example of how you can dynamically import a module when the user clicks on a button:
document.getElementById('button').addEventListener('click', async () => {
const { func } = await import('./module.js');
func();
});
globalThis
JavaScript is used in a variety of environments such as web browsers, Node.js, Web Workers, and so on.
Each of these environments has its own object model and a different syntax to access it.
ES2020 brings us the globalThis
property which always refers to the global object, no matter where you are executing your code.
This property really shines when you aren't sure what environment the code is going to run in.
The following is the example of using setTimeout function in Node.js using globalThis:
globalThis.setTimeout(() => console.log("Hello world"), 3000)
Hello
As well as in web browser
Promise.allSettled()
This method returns a promise that resolves after all of the given promises are either fulfilled or rejected. It is typically used where asynchronous tasks do not depend upon one another to complete successfully, as illustrated in the following example:
const promise1 = Promise.resolve(2);
const promise2 = new Promise((resolve, reject) =>
setTimeout(reject, 1000, 'Something went wrong')
);
const promises = [promise1, promise2];
Promise.allSettled(promises).then((results) =>
results.map((res) => console.log(res))
);
// Object { status: "fulfilled", value: 2 }
// Object { status: "rejected", reason: "Something went wrong" )
// [ undefined, undefined ]
Nullish Coalescing Operator
This operator will return a Right Hand Side operand when the Left Hand Side operand is either undefined or null.
The syntax for this operator is:
const employee = {};
const name = employee.name ?? 'Joe';
In the example above, the operator will set the value of name as 'Joe' as employee.name is undefined.
At first glance this looks exactly the same as a logical OR operator ( || ), however, logical OR operator Right Hand Side operand when Left Hand Side Operand is false (undefined, null, “”, 0, false, NaN). Below is the comparison of both operators:
let name;
console.log(name ?? 'Joe'); // 'Joe'
console.log(name || 'Joe'); // 'Joe'
name = null;
console.log(name ?? 'Joe'); // 'Joe'
console.log(name || 'Joe'); // 'Joe'
name = NaN;
console.log(name ?? 'Joe'); // NaN
console.log(name || 'Joe'); // 'Joe'
name = 0;
console.log(name ?? 'Joe'); // 0
console.log(name || 'Joe'); // 'Joe'
name = false;
console.log(name ?? 'Joe'); // false
console.log(name || 'Joe'); // 'Joe'
name = '';
console.log(name ?? 'Joe'); // ''
console.log(name || 'Joe'); // 'Joe'
Chaining Nullish Coalescing Operator ( ?? ) with AND ( && ) or OR ( || ) operators
It’s not possible to chain AND ( && ) and OR ( || ) operators directly with ?? operator. If you need to combine them, then you must wrap && or || operator in the parenthesis
Let's look at an example:
const employee = { firstName: null, lastName: null };
const name = employee.firstName || employee.lastName ?? 'Anonymous'; // error
const name = (employee.firstName || employee.lastName) ?? 'Anonymous'; // 'Anonymous'
Optional Chaining
Optional Chaining syntax allows you to access deeply nested objects without worrying about whether the property exists or not. While working with objects, you must be familiar with an error of this kind:
TypeError: Cannot read property <xyz> of undefined
The above error means that you are trying to access the property of an undefined variable.
To avoid such errors, your code will look like this:
const employee = {
name: 'Joe',
age: 25,
address: {
street: {
number: 12,
name: 'Main',
},
},
};
const address =
employee &&
employee.address &&
employee.address.street &&
employee.address.street.number;
console.log(address);
Instead of checking each node, optional chaining handles these cases with ease.
Below is the same example using optional chaining:
const employee = {
name: 'Joe',
age: 25,
address: {
street: {
number: 12,
name: 'Main',
},
},
};
const address = employee?.address?.street?.number;
console.log(address);
Pretty simple isn't it?
You can also check arrays and functions using optional chaining. An example is given below:
let colors = ['red', 'green', 'blue'];
console.log(colors?.[1]); // 'green'
colors = null; // set array to null
console.log(colors?.[1]); // undefined
let func = () => 'Hey there!';
console.log(func?.[1]); // 'Hey there!'
func = null; // set function to null
console.log(func?.()); // undefined
Conclusion
The introduction of ES2020’s new features add even more flexibility and power to the constantly evolving JavaScript.
I hope you found this article useful and that you are as excited as I am about using these features!