Skip to main content

New and potential ES2019 JavaScript features every developer should be excited about

An overview of new ES2019 JavaScript features
JavaScript has come a long way since its early days, with many new additions and features designed specifically to make the language more user-friendly and less verbose. Below are some recent additions to JavaScript that I find fascinating.
Some of these features are already available in Node, Chrome, Firefox, and Safari, while others are still in the proposal stage.

Optional chaining

Optional chaining is done using the ?. operator. It primarily ensures that the preceding value before the question mark is neither undefined nor null. This is really useful when assessing the properties of deeply nested objects.
There’s a need to be sure that the ?. operator exists before assessing the properties.
Consider the following example:
const users = [
  {
   name: "Olagunju Gbolahan",
   occupation: "Software Developer",
   sayName(){
    console.log(`my name is ${this.name}`);
   },
   address: { office: "New York" }
  },
  { name: "Olawaseyi Moses" },
  { name: "Tunde Ednut" }
];
Let’s consider the second user in the array of users:
const secondUser = users[1];
We may want to get the office address of this user. Before the advent of the optional chaining operator, we would have to go through a relatively inefficient process to obtain this information:
const theAddress = secondUser.address && secondUser.address.office;
console.log(theAddress); // undefined
If we had a deeply nested object, we would have to check that its value existed using && operator on each level.
But with the optional chaining, we simply do the following:
const theAddress = secondUser?.address?.office;
console.log(theAddress); // undefined
We can also use optional chaining with object methods to confirm they exist before execution:
const firstUser = users[0];
console.log(firstUser.sayName?.()); // my name is Olagunju Gbolahan
It will simply return undefined if a method with the given name doesn’t exist on the object.
console.log(firstUser.sayOccupation?.()); // undefined
Because the optional chaining operator hasn’t been added to the JavaScript specification yet, it is still in the proposal stage.
You can use it today with the babel-plugin-proposal-optional-chaining plugin.

Optional catch binding

This feature comes in handy when we know beforehand what our error will be, and we don’t want the redundancy of unused variables.
Consider the traditional try and catch block:
try {
  const parsedJsonData = JSON.parse(obj);
} catch (error) {
  //the variable error has to be declared whether used or unused
  console.log(obj);
}
But with the addition of optional catch binding, we don’t have to provide unused variables — especially when we have defaults for our try block.
function getName () {
  let name = "Gbolahan Olagunju";
  try {
    name = obj.details.name
  } catch {}
  console.log(name);
}

The pipeline operator

This is one of the proposed additions to Javascript and it is currently at stage 1.
It essentially helps make several function calls to the same argument readable.
It does this by piping the value of an expression as argument(s) to a function. Consider calling the following functions without the pipeline operator |>.
const capitalize = (input) =>  input[0].toUpperCase() + input.substring(1);
const removeSpaces = (input) => input.trim();
const repeat = (input) => `${input}, ${input}`;
const withoutpipe = repeat(capitalize(removeSpaces('    i am gbols    ')));
console.log(withoutpipe); // I am gbols, I am gbols
But with the pipeline operator, readability can be greatly improved:
const withpipe = '    i am gbols    '
                |> removeSpaces
                |> capitalize
                |> repeat;
console.log(withpipe); // // I am gbols, I am gbols

String.trimStart and String.trimEnd

This was formally named trimRight and trimLeft, but with ES2019 the names were changed to the aliases trimStart and trimEnd to make them more intuitive to users.
Consider the following example:
let message = "     Welcome to LogRocket      ";
message.trimStart(); // "Welcome to LogRocket      "
message.trimEnd(); // "Welcome to LogRocket";

Object.fromEntries

Before talking about Object.fromEntries, it is important to talk about Object.entries.
The Object.entries method was added to the ES2017 specification to provide a way to convert an object into its array equivalent, thus granting it access to all array methods for processing.
Consider the following object:
const devs = {
  gbols: 5,
  andrew: 3,
  kelani: 10,
  dafe: 8,
};
const arrOfDevs = Object.entries(devs);
console.log(arrOfDevs);
//[
//  ["gbols", 5]
//  ["andrew", 3]
//  ["kelani", 10]
//  ["dafe", 8]
//]
Now, we can use the filter method on arrays to get devs that have more than 5 years experience:
const expDevs = arrOfDevs.filter(([name, yrsOfExp]) => yrsOfExp > 5);
console.log(expDevs);
//[
//  ["kelani", 10]
//  ["dafe", 8]
//]
Then a problem arises: there is no easy way to convert the results back into an object. Usually, we would write our own code to transform this back into an object:
const expDevsObj = {};
for (let [name, yrsOfExp] of expDevs) {
expDevsObj[name] = yrsOfExp;
}
console.log(expDevsObj);
//{
 //dafe: 8
 //kelani: 10
//}
But with the introduction of Object.fromEntries, we can do this in one swipe:
console.log(Object.fromEntries(expDevs));
//{
 //dafe: 8
 //kelani: 10
//}

Flat

Oftentimes, we have deeply nested arrays to deal with as a result of an API call. In this case, it’s especially important to flatten the array.
Consider the following example:
const developers = [
  {
    name: 'Gbolahan Olagunju',
    yrsOfExp: 6,
    stacks: ['Javascript', 'NodeJs', ['ReactJs', ['ExpressJs', 'PostgresSql']]]
  },
  {
    name: 'Daniel Show',
    yrsOfExp: 2,
    stacks: ['Ruby', 'Jest', ['Rails', ['JQuery', 'MySql']]]
  },
  {
    name: 'Edafe Emunotor',
    yrsOfExp: 9,
    stacks: ['PHP', 'Lumen', ['Angular', 'NgRx']]
  }
];
const allStacks = developers.map(({stacks}) => stacks);
console.log(allStacks);
// [
// ['Javascript', 'NodeJs', ['ReactJs', ['ExpressJs', 'PostgresSql']]]
// ['Ruby', 'Jest', ['Rails', ['JQuery', 'MySql']]]
// ['PHP', 'Lumen', ['Angular', 'NgRx']]
// ]
The allstacks variable contains deeply nested arrays. To flatten this array, we can use the Array.prototype.flat.
Here’s how:
const flatSingle = allStacks.flat();
console.log(flatSingle);
//[
// "JavaScript",
//  "NodeJs",
// ['ReactJs', ['ExpressJs', 'PostgresSql']]]
// "Ruby",
// "Jest",
// ['Rails', ['JQuery', 'MySql']]]
// "PHP",
// "Lumen"
// ["Angular", "NgRx"]
//]
We can deduce from the above that the array has been flattened one level deep, which is the default argument to array.prototype.flat.
We can pass an argument to the flat method to determine the degree to which we want to flatten.
The defaults argument is a value of 1. To completely flatten the array, we can pass an argument of Infinity. The Infinityargument flattens the array completely, irrespective of the depth of the array.
Here’s how:
const completelyFlat = allStacks.flat(Infinity);
console.log(completelyFlat);
//[
// "JavaScript",
// "NodeJs",
// "ReactJs",
// "ExpressJs",
// "PostgresSql",
// "Ruby",
// "Jest",
// "Rails",
// "JQuery",
// "MySql",
// "PHP",
// "Lumen",
// "Angular",
// "NgRx"
//]

FlatMap

FlatMap is a combination of calling the map method and the flat method with a depth of 1. It is often quite useful as it does the same thing in a very efficient manner.
Below is a simple example of using both map and flatMap:
let arr = ['my name is Gbols', ' ', 'and i am great developer']; 
console.log(arr.map(word => word.split(' ')));
//[
// ["my", "name", "is", "Gbols"],
// ["", ""],
// ["and", "i", "am", "great", "developer"]
//]
console.log(arr.flatMap(word => word.split(' ')));
//[ "my"
//  "name"
//  "is"
//  "Gbols"
//   ""
//   ""
//   "and"
//   "i"
//   "am"
//   "great"
//   "developer"
//]

Implementing new JS features? Understand how JavaScript errors affect your users.

Comments

Popular posts from this blog

How to use Ngx-Charts in Angular ?

Charts helps us to visualize large amount of data in an easy to understand and interactive way. This helps businesses to grow more by taking important decisions from the data. For example, e-commerce can have charts or reports for product sales, with various categories like product type, year, etc. In angular, we have various charting libraries to create charts.  Ngx-charts  is one of them. Check out the list of  best angular chart libraries .  In this article, we will see data visualization with ngx-charts and how to use ngx-charts in angular application ? We will see, How to install ngx-charts in angular ? Create a vertical bar chart Create a pie chart, advanced pie chart and pie chart grid Introduction ngx-charts  is an open-source and declarative charting framework for angular2+. It is maintained by  Swimlane . It is using Angular to render and animate the SVG elements with all of its binding and speed goodness and uses d3 for the excellent math functio...

Understand Angular’s forRoot and forChild

  forRoot   /   forChild   is a pattern for singleton services that most of us know from routing. Routing is actually the main use case for it and as it is not commonly used outside of it, I wouldn’t be surprised if most Angular developers haven’t given it a second thought. However, as the official Angular documentation puts it: “Understanding how  forRoot()  works to make sure a service is a singleton will inform your development at a deeper level.” So let’s go. Providers & Injectors Angular comes with a dependency injection (DI) mechanism. When a component depends on a service, you don’t manually create an instance of the service. You  inject  the service and the dependency injection system takes care of providing an instance. import { Component, OnInit } from '@angular/core'; import { TestService } from 'src/app/services/test.service'; @Component({ selector: 'app-test', templateUrl: './test.component.html', styleUrls: ['./test.compon...

How to solve Puppeteer TimeoutError: Navigation timeout of 30000 ms exceeded

During the automation of multiple tasks on my job and personal projects, i decided to move on  Puppeteer  instead of the old school PhantomJS. One of the most usual problems with pages that contain a lot of content, because of the ads, images etc. is the load time, an exception is thrown (specifically the TimeoutError) after a page takes more than 30000ms (30 seconds) to load totally. To solve this problem, you will have 2 options, either to increase this timeout in the configuration or remove it at all. Personally, i prefer to remove the limit as i know that the pages that i work with will end up loading someday. In this article, i'll explain you briefly 2 ways to bypass this limitation. A. Globally on the tab The option that i prefer, as i browse multiple pages in the same tab, is to remove the timeout limit on the tab that i use to browse. For example, to remove the limit you should add: await page . setDefaultNavigationTimeout ( 0 ) ;  COPY SNIPPET The setDefaultNav...