In this post, we are going to learn about the wonderful features of ES2020. ES2020 also know as ES11 which is the latest version of JavaScript.
Initial Setup for ES11 Features
All the latest versions of browsers javascript engines and Node JS support ES2020 features. On the older version of browsers and Node JS, We could do this setting in .babelrc config of babel setup to enable ES2020.
{
"plugins": [
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods",
"@babel/plugin-syntax-bigint"
]
}
Latest Features of ES2020 or ES11
1. The optional chaining(?.)
The optional chaining operator(?.) is used to get the values of nested deeply connected objects without validating the expression. It is somewhat like the dot(.) operator, besides it does not throw an error if the expression, the function is (null or undefined). It uses short circuits that return values of undefined
Syntax
object.value?.property
object.array?.[index]
object.functionname?.(arguments)
Accessing existing property of deeply nested object.
When we will check deeply nested object existing intermediate property. we will get the value of the property without any error.
const Country = {
Name: 'US',
City:{cityname:'CA', Town:'WA',
Details: {Location: 'US',POP:10000,Area:4500}
}
};
var Location = Country.City.Details.Location;
console.log(`The location is = ${Location}`)
Output
The location is = US
Accessing not Existing Property of deeply Nested object
When we will try to get a deeply nested object, not an existing property. we will get the following error.
TypeError: Cannot read property of undefined
Let us understand the above error with an example
const Country = {
Name: 'US',
City:{cityname:'CA', Town:'WA'} ,
}
var Location = Country.City.Details.Location;
console.log(Location)
Output
TypeError: Cannot read property 'Location' of undefined
Fixing the Type-error Using optional chaining(?.)
We can fix this code in JavaScript as shown below ES11 optional chaining(?.) operator fixing type error
const Country = {
Name: 'US',
City:{cityname:'CA', Town:'WA'} ,
}
var Location =
Country.City && Country.City.Details && Country.City.Details.Location;
console.log(Location)
Output
undefined
1. Optional chaining(?.) with object property
We had to code so much to make our code run. We can achieve the same with less and clear code in ES11 using The optional chaining(?.).
Let us understand with an example.
const Country = {
Name: 'US',
City:{cityname:'CA', Town:'WA'} ,
}
var Location = Country?.City?.Details?.Location;
console.log(Location)
Output
undefined
2.Optional chaining(?.) with array
let countries = ['US', 'India', 'Japan']
console.log(countries[1]) // India
countries = null
console.log(countries?.[1]) // undefined
console.log(countries[1]) // TypeError: Cannot read property '1' of null
3. Optional chaining(?.) with function
let getcountries = () => {
return 'Japan'
}
console.log(getcountries()) // Japan
getcountries = null
console.log(getcountries()) // TypeError: getcountries is not a function
console.log(getcountries?.()) // undefined
2. GlobalThis
Earlier than ES2020, to access the object global across environments, We had to use different ways across the environments.
Environments
- Web: window, self, or frame.
- Web Worker: Self
- Node JS: Global
In this Digital World, we use the applications across environments, Yes you heard it right, ES11 provides ‘GlobalThis‘ property to access the object across the environments, irrespective of the environments.
Note:
if we define variables or functions with ‘var‘ in Bowers,it become the global object,define variable or function with let,const does not make them global.
var gobalobj = 50;
console.log(`global obj= ${window.gobalobj}`);
Output
global obj= 50
String.prototype.matchAll()
The matchall() function returns the iterator, iterator generates an array of all matches against a regular expression, including the captured group. The iterator work wonderful with for…of loops.
Syntax
string.matchall(regexp)
It takes one parameter. It is a Regular expression against which we are matching the string.
Note: It is a must-have object with /g global flag in the matchall() function. Otherwise, the error will be thrown
“String.prototype.matchAll called with a non-global RegExp argument“
Let us understand with an example.
let regexp = /(\d+)/g;
let string = '12345 string with 679 number';
var matches = string.match(regexp)
console.log(`array first index value= ${matches[0]}`)
//for of loop over the matches
for (const match of matches)
{
console.log(match)
}
Output
array first index value= 12345
12345
679
3. Dynamic Import
Earlier than 2020, in JS the way to import modules is static as here.
import * as TestModule from "./testmodules.js";
Cons of this statement:
- All the code of this imported module is evaluated at the load time of the parent module.
- Static importing make the code slow and increase memory usages.
- Error in the importing module does not know until it is used.
Using Dynamic import we can import module conditionally using async/await. It is also known as code splitting. The dynamic Import syntax makes us call Import as a function that return a promise.
if(true){
let module = await import('/modules/testmodules.js');
}
4. BigInt
The largest safe Integer number in JavaScript can be 253 – 1 and also know as Number.MAX_SAFE_INTEGER. If we go beyond Number.MAX_SAFE_INTEGER
, it is not safe in JS.
console.log(Number.MAX_SAFE_INTEGER+10);
Output
9007199254741000
In ES2020 we can achieve this and solve this problem by following ways
- Create BigInt appending
n
to the end of an integer literal. - by calling
BigInt()
function
Let us understand this with an Example.
const bigintNum = BigInt(Number.MAX_SAFE_INTEGER)
console.log(Number.MAX_SAFE_INTEGER)
const bigintPlusone = bigintNum + 1n
console.log(bigintPlusone)
Output
9007199254740991
9007199254740992n
5. Promise.allSettled()
Earlier than 2020, In JavaScript, Promise.all() is used to wait for multiple dependent promises to complete.It is resolved if all the promises are fulfilled, rejected when only a single Promise fails.
This problem is that Promise.all() does not have a direct way to get the result of all the promises when at least one of them is rejected.
Whereas ES11 Promise.allSettled() method return a promise that resolves after all promises to be settled, regardless of their result.(fulfilled or rejected).It returns an iterable object such as an array that contains the result of each Promise outcome(fullfilled or rejected).
const promiseobj1 = Promise.resolve(4);
const promiseobj2 = new Promise((resolve, reject) => setTimeout(reject, 200, 'promiseresult'));
const promises = [promiseobj1, promiseobj2];
Promise.allSettled(promises).
then((outputs) => outputs.forEach((output) => console.log(output.status)));
Output
fulfilled
rejected
6. Nullish coalescing Operator(??)
These are the “falsy” values in JavaScript
- null
- undefined
- empty string
- 0
- not a number-NaN
Earlier, ES11 || operator is used to assign the default values to variables When variable assigning is null or undefined.The problem with || is that all the falsy values are overridden by default values.It is not expected behavior.
const Null_obj = null || 'default string';
const empty_str = "" || 'empty String'
const num = 0 || 20;
const nan = NaN||30
console.log(Null_obj);
console.log(empty_str);
console.log(num);
console.log(nan);
Output
default string
empty String
20
30
Nullish coalescing operator ?? return the default value if left-hand side value null or undefined else left hand side values is returned.
const Null_obj = null ?? 'default string';
const empty_str = "" ?? 'empty String'
const num = 0 ?? 20;
const nan = NaN??30
console.log(Null_obj);
console.log(empty_str);
console.log(num);
console.log(nan);
Output
"default string"
""
0
NaN
7. Private field in class
Private properties can be used only inside of a class. ES11 introduced the features of classes Private property.To define a private property prefix property by hash symbol (#).
class State {
#statename = "MN";
constructor(country) {
this.country = country;
}
get_statename() {
return this.#statename;
}
}
const state = new State("US");
console.log(state.get_statename()); //MN
console.log(state.#Statename) //Error: Private field '#Statename' must be declared in an enclosing class