Blog home >What’s new in JavaScript

Technology

10 min read

What’s new in JavaScript

Last Updated On Wed Mar 13 2024

“Any application that can be written in JavaScript, will eventually be written in JavaScript.”  — Jeff Atwood, Co-founder of StackOverflow

Javascript is currently being used in more than 94% of websites. That means millions of web developers are using JavaScript for web application development. The ease of use and widespread adoption of this programming language is exactly why it continues to become more important to web developers.

We at Invygo, write a lot of Javascript code each day for our various tech platforms. So we just thought of sharing some of the cool new 🎊 features of ES2019.

Array: flat and flatMap

These (flat and flatMap) are prototype methods on the Array object.

Array.flat

In order to flatten an array, we now have a new flat(n) prototype method on an array which flattens the array to the nth depth and returns a new array. The default value of n is 1. We can pass n as Infinity to flatten any level deep nested arrays 😄.

const letters = ['a', ['b', ['c', ['d', 'e']]]];
console.log( letters.flat() ); // ['a', 'b', ['c', ['d', 'e']]]
console.log( letters.flat(2) ); // ['a', 'b', 'c', ['d', 'e']]
console.log( letters.flat(Infinity) ); // ['a', 'b', 'c', 'd', 'e']

Support: TC39: Stage 4, Node: 11+, Chrome: 69+, Firefox: 62+

Array.flatMap

Consider an example where we need to create a duplicate of each item in array, we can acheive this by using map followed by flat ☹️ .

const digits = [1, 2, 3, 4];
const copy = digits.map( n => [ n, n ] )
console.log( copy ); // [[1,1],[2,2],[3,3], [4,4]]
console.log( copy.flat() ); // [1, 1, 2, 2, 3, 3, 4, 4]

We can instead use flatMap prototype method to perform both mapping and flattening functionalities in a single syntax. 😃

Note:- flatMap can only flatten the array returned from the callback function to the depth of 1.

const digits = [1, 2, 3, 4];
const copy = n => [ n, n ];
console.log( digits.flatMap( copy ) ); // [1, 1, 2, 2, 3, 3, 4, 4]

Support: TC39: Stage 4, Node: 11+, Chrome: 69+, Firefox: 62+

Stable Sort

ECMAScript never proposed a sorting algorithm for the JavaScript engine, it only enforces a syntax of the sort API. Hence depending upon a browser or JavaScript engine, we often get variations in sorting performance and/or sort stability. But as of now, ECMAScript enforces the sorting of an array to be stable. A sort algorithm is stable if the result of the sort, maintains the order of the items which were unaffected by the sort, maintains the same order in which they were originally inserted.

const list = [
  { name: 'John', scores: 11 },
  { name: 'Max', scores: 35 },
  { name: 'Shaun', scores: 18 },
  { name: 'Harry', scores: 35 }
];
// sort in descending order of scores
list.sort( ( a, b ) => b.scores - a.scores );
// possible result
[
  { name: 'Harry', age: 35 }
  { name: 'Max', age: 35 },
  { name: 'Shaun', age: 18 },
  { name: 'John', age: 11 },
]

In the above example, in the list array, the item with the name Harry comes before the item with the name Max. Since these items have the same scores, we would expect sort result to maintain the same order but sometimes, that’s not the case. The result of the sort algorithm depends on which JavaScript engines used. But now, all modern browsers and Node.js uses stable sort by default with the sort method. The below result will be acheived consistently.

// stable sort result
[
  { name: 'Max', age: 35 }
  { name: 'Harry', age: 35 },
  { name: 'Shaun', age: 18 },
  { name: 'John', age: 11 },
]

Support: Node: 12+, Chrome: 70+, Firefox: 62+

Object: fromEntries

We can extract key:value pairs of an object using Object.entries which returns an array with each element being an array that contains key as the first item and value as the second item. But there was no static method on Object to create object from array on such entries.

const obj = { x: 1, y: 2, z: 3 };
const objEntries = Object.entries( obj );
console.log( objEntries ); // [["x", 1],["y", 2],["z", 3]]

We now have fromEntries static method on the Object which converts entries back to object.

const entries = [["x", 1],["y", 2],["z", 3]];
const obj = Object.fromEntries( entries );
console.log( obj ); // {x: 1, y: 2, z: 3}

We used entries to easily filter and map object values. But until now, it was a hassle putting back entries back to the object form. This is where fromEntries can be useful.

const obj = { x: 1, y: 2, z: 3 };
const objEntries = Object.entries( obj ); // [["x", 1],["y", 2],["z", 3]]
const evenValues = objEntries.filter(
( [key, value] ) => value % 2 === 0 // select values which are even
); // [["y", 2]]
console.log( Object.fromEntries( evenValues ) ); // {y: 2}

Support: TC39: Stage 4, Node: 12+, Chrome: 73+, Firefox: 63+

Promises

We are aware of all and race static methods on Promise constructor. Promise.all([...promises]) returns a promise which resolves after all the input promises resolve and rejects when any of the input promises gets rejected. Promise.race([...promises]) returns a promise which resolves as soon as any of the input promises resolves and rejects as soon as any of the promises rejects. There comes the need to have a static method that returns a promise which resolves after all of the promises are completed (either resolved or rejected). We also needed a race like method that returns a promise which waits until any of the input promises resolve.

Promise.allSettled

Promise.allSettled method accepts an array of promises and resolves once all of the promises have either resolved or rejected. Hence, promise returned by this method does not require catch callback as it will always resolve. The then callback receives the status and value of each promise in the order of their appearance.

const promise1 = () => new Promise(
 (resolve, reject) => setTimeout( () => resolve( 'value1' ), 1000 )
);


const promise2 = () => new Promise(
 (resolve, reject) => setTimeout( () => reject( 'error2' ), 2000 )
);


const promise3 = () => new Promise(
 (resolve, reject) => setTimeout( () => resolve( 'value3' ), 1500 )
);
const p = Promise.allSettled( [promise1(), promise2(), promise3()] ).then(
 ( values ) => console.log( values )
);
// Output
[
 {status: "fulfilled", value: "value1"}
 {status: "rejected", value: "error2"}
 {status: "fulfilled", value: "value3"}
]

Support: TC39: Stage 3, Chrome: 76+

Promise.any

Promise.any method is similar to Promise.race but the promise returned by this method does not execute the catch block as soon as any of the promises gets rejected. Instead, it waits until any of the promises resolves. If none of the promises is resolved, catch block will get executed. If any of the promises have resolved first, then block will be executed.

Support: TC39: Stage 1

Numeric Separators

Readability becomes a major issue when we write large integers or decimals, say for e.g: 1000000000 is one billion but one needs to count zeros carefully.In the newer versions of JavaScript, we can use _ separator using which we can separate parts of a number to enhance readability.

const billion = 1_000_000_000;
console.log( billion ); // 1000000000

We can put _ wherever we want in a number and JavaScript will simply ignore it. This works fine on any kind of number, whether it is an integer, decimal, binary, hexadecimal or octal.

console.log( 2_000_000_000.11 ); // 2000000000.11
console.log( 0b1001_1010_01 ); // 617
console.log( 0o11_51 ); // 617

Support: TC39: Stage 3, Node: 12.5+, Chrome: 75+

Private class fields

As we know, JavaScript doesn’t have property modifiers like public, private and protected. All properties on an object are public by default, which means anybody can access them. The closest we can come to defining a property which is hidden from the outside world is by using property name which is Symbol. You might have used _ prefix to denote properties which are meant to be private but it’s just notation and doesn’t solve the problem. With the private class fields, we can make class properties only accessible inside the class only and prevent them from reflecting on the instance (object). A private class field can be defined in the same way a public class field is defined but instead of adding underscore prefix, we have to add # prefix. Accessing private property on an object will result in SyntaxError: Undefined private field

class Person {
  #name = 'John'; // this is private
  showName() {
    console.log( this.#name );
  }
}
// create instance
const person = new Person();
person.showName() // John
//console.log( person.#name ); // SyntaxError

Private properties are only accessible inside the class where they are defined. Hence private properties won’t be accessible inside parent or child class. We can also define private properties with undefined values.

class Person {
  #name;
  constructor( name ) {
    this.#name = name;
  }
  showName() {
   console.log( this.#name );
  }
}
// create instance
const john = new Person( 'John' );
john.showName(); // John

Support: TC39: Stage 3, Node: 12+, Chrome: 74+

Well these are just some of them, there are many more exciting new features such as RegExp Lookbehind, matchAll, BigInt, globalThis etc. Do google these topics, and Happy Coding !! 👍

Similar Content

Troubleshooting Guide: Why Your Car Won't Go in Reverse

Cars

4 min read

Troubleshooting Guide: Why Your Car Won't Go in Reverse

Is Your Car Slow to Accelerate?

Cars

6 min read

Is Your Car Slow to Accelerate?

Understanding Car Headers and Their Impact on Performance

Cars

6 min read

Understanding Car Headers and Their Impact on Performance

invygo Tech FZ LLC | info@invygo.com

358-361, Dubai Internet City Building 17, Dubai, UAE.