New Features in JavaScript 2020 or ECMAScript2020
Although it is a little late to talk about this, 11th edition of ECMAScript language specification was published in 2020(ECMAScript 2020). Some of the key new features of this 11th edition, have been discussed below.
Dynamic Imports
The standard import syntax in JavaScript is static. Static import statement looks like:
import * as newModule from ‘/modules/dynamicmodule.js’;
This will always evaluate the code of the imported module at the time of loading the module that imports it. While static imports are still the preferred way to load initial dependencies, its static nature can cause problems in many situations, such as:
- Importing some modules can slow down the initial loading of your code even though you are going to use this imported code much later after initial loading.
- Modules being imported do not exist at load time.
- The specifier string of the import can only be constructed dynamically.
The new feature of dynamic imports lets you call import as a function, which would then return a Promise. This form also supports await keyword. It allows you to load modules conditionally or on-demand at run time.
Dynamic import can be done in two ways:
- Using import as a function returning a promise
import(‘./dynamicmodule.js’).then((newModule) => {// Do something with the module.}); - Using await keyword
If (condition) {const newModule = await import(‘./dynamicmodule.js’);newModule.function();}
Import Metadata
The import.meta object exposes context-specific metadata to a JavaScript module. It contains information about the module, like the module’s URL.
In this object, import is not an object. In fact import.meta is an object created by the ECMAScript implementation, with a null prototype. The object is extensible, and its properties are writable, configurable, and enumerable.
<script type=”module” src=”my-module.js”></script>
You can access meta information about the module using the import.meta object.
console.log(import.meta);
This statement will return an object with url property indicating the baseURL of the module including the query parameters.
New export syntax
There has not been any symmetric export syntax in JavaScript until now to export a namespace. So when you have to export a namespace, you are required to use the following two statements to export the namespace NewModule .
import * as NewModule from ‘./new-module.js’;
export { NewModule }
This is not very convenient from a developer’s point of view.
However now, there is a new export syntax in JavaScript 2020 which makes exporting a namespace symmetric to importing the namespace.
export * as NewModule from ‘./new-module.js’;
BigInt
BigInt is the new data type in JavaScript 2020 that is used to represent whole numbers larger than 2ˆ53 – 1. For a very long time now, JavaScript only had one data type to represent whole numbers and that was ‘Number’. The maximum re-presentable value with data type ‘Number’ is 2ˆ53, corresponding to the Number.MAX_SAFE_INTEGER constant.
Having only ‘Number’ data type to represent whole numbers with an upper limit of 2ˆ53 has been posing lot of challenges for JavaScript developers in many situations, such as:
- Interaction with other systems that provide data as 64-bit integers, such as GUIDs, account numbers, or object IDs.
- Result of complex mathematical calculations requiring more than 64 bits.
BigInt solves these problems. BigInt can be represented by appending ‘n’ to the literal or by using its constructor.
const aBigInteger = 98765432123456789n;
const aBigInteger = BigInt(“98765432123456789”);
BigInt and Number are different data types so they can not be mixed. Numbers of type BingInt can not be used with methods in the built-in Math object and cannot be mixed with instances of Number in operations; they must be coerced to the same type.
The matchAll method for regular expressions
Performs a regular expression match of the String representing the this value against regexp and returns an iterator. Each iteration result’s value is an Array object containing the results of the match, or null if the String did not match.
The globalThis Object
globalThis standardizes accessing the global this object across environments. Instead of writing ‘window’, ‘self’ and ‘global’ depending on the environment, we can simply write globalThis to access the global this object.
The Promise.allSettled() method
The Promise.allSettled() method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.
It is typically used when you have multiple asynchronous tasks that are not dependent on one another to complete successfully, or you’d always like to know the result of each promise.
New operators
A couple of new operators have been introduced to make it easier to write and read your code:
-
- The nullish coalescing operator
Consider following code that we have been using to assign default value:
const size = settings.size || 42;
It assigns the default value of 42 to size when settings.size is null, undefined, “ “, 0 or false. However, “ “, 0 or false could be valid values for certain variable types.
With new nullish coalescing operator, the default value of 42 would be assigned only when settings.size is null or undefined.
const size = settings.size ?? 42;
-
- Optional Chaining operator
A more compact and readable way to write following piece of code
const username = txtName ? txtName.value : undefined;
which with Optional Chaining operator would become
const username = txtName?.value;
Both will now give the same result of assigning the value of txtName to username if txtName is not null or undefined otherwise.
This operator is most useful in
-
- Complex expressions such as invoice?.customer?.address?.city;
- Dynamic properties user?.[“name”]
- Function or method calls to check if a particular method exists. It is executed if the method exists otherwise the expression returns undefined. user.getFullName?.();