JS ES11 wonderful features

JavaScript

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:

  1. All the code of this imported module is evaluated at the load time of the parent module.
  2. Static importing make the code slow and increase memory usages.
  3. 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