Stay Ahead of the Curve: Must-Try ES8 to ES13 JavaScript Features

Raghav Bang
Published in
5 min readApr 15


Enhance the quality of your JavaScript code with these powerful features!!

ECMAScript 8 Features:

  1. Object.entries:

It will return all properties of an object in an array in form of key and value.

   const client={
// Output: [["firstName", "Karan"],["lastName", "Malhotra"]]

Whereas for an array, it will also return array but in the following manner [ [index,value]] format.

const values = [10,20,30,40]
//Output [["0", 10],["1", 20],["2", 30],["3", 40]]

2. Object.values():

It will return values of all keys of an object in an array.

const client={
console.log(Object.values(client)) // Output: ["Karan", "Malhotra"]

ECMAScript 9 Features:

1. for await of loop:

The for await...of loop is a new addition to the language as of ECMAScript 2018 (ES9), and it allows you to iterate over asynchronous iterators. An asynchronous iterator is an object that returns a promise for each value it produces when iterated over.

Before the introduction of for await...of, you could use a regular for...of loop to iterate over synchronous iterators (like arrays), but you would need to handle promises and callbacks separately when iterating over asynchronous data. The for await...of loop simplifies this process by automatically awaiting each promise before moving on to the next iteration.

function fakePromise(delay, value, shouldSucceed = true) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldSucceed) {
} else {
reject(new Error(`Promise failed with value: ${value}`));
}, delay);

async function getData() {
const responses = await Promise.allSettled([
fakePromise(0, "1"), fakePromise(1000, "2", false), fakePromise(2000, "3")

for await (const response of responses) {



"status": "fulfilled",
"value": "1"
"status": "rejected",
"reason": "Error: Promise failed with value: 2"
"status": "fulfilled",
"value": "3"

ECMAScript 10 Features:

1. Array.flatMap():

It is used to transform an array by mapping each element to a new value using a mapping function, and then flattening the result into a new array. The mapping function should return an array, and flatMap() will concatenate the arrays returned by each element of the original array.

const numbers = [1, 2, 3, 6, 9];

const result_1 = numbers.filter(number => number > 2).map(number => number * 2)
console.log(result_1); // Output: [6, 12, 18]

// Using flatMap
const result_2 = numbers.flatMap(x => x > 2 ? [x * 2] : []);

console.log(result_2); // Output: [6, 12, 18]

2. Object.fromEntries():

It is used to transform an array of key-value pairs into an object. It takes an iterable (such as an array) of key-value pairs and returns a new object with properties corresponding to the keys and values of the iterable.

const entries = [
['name', 'John'],
['age', 30],
['gender', 'male']

const obj = Object.fromEntries(entries);

console.log(obj); // Output: {name: "John", age: 30, gender: "male"}

3. Symbol.prototype.description():

It is used to retrieve the description of a Symbol object. A Symbol is a unique and immutable data type that can be used as an identifier for object properties. The description of a Symbol is a string that can be used to describe its purpose.

const mySymbol = Symbol('Data');

console.log(mySymbol.description); // Output: "Data"

4. Optional Catch Binding:

Prior to ES10, when catching an error in a try-catch block, it was necessary to provide a binding (i.e., a variable) for the caught error. This meant that even if you didn’t need to use the error object, you still had to define a variable to hold it, like so:

try {
// some code that may throw an error
} catch (error) {
// do something with error

Optional Catch Binding allows to omit the binding in the catch clause if you don’t need to use the caught error object. You can simply omit the binding and still catch the error.

try {
// some code that may throw an error
} catch {
// do something when an error is caught
// but don't need to use the error object

5. Array Sort Stability:

Prior to ES10, the sort() method was not guaranteed to be stable, which means that the order of elements with equal values was not necessarily preserved during the sort.

In ES10, the “Array Sort Stability” feature was introduced, which guarantees that the sort() method will be stable. This means that the order of elements with equal values will be preserved during the sort, making it easier to reason about and predict the behavior of the sort() method.

Earlier sort() was using Quick Sort Algorithm. But now it uses TimSort Algorithm.

ECMAScript 11 Features:

  1. BigInt:

BigInt allows you to work with numbers that are larger than the maximum number that can be represented by the Number data type in JavaScript (which is 2⁵³ — 1).

BigInts are created by appending the letter “n” to the end of an integer literal or by calling the BigInt() constructor with an integer value as its argument.

const bigInt1 = 1234567890123456789012345678901234567890n;
const bigInt2 = BigInt("9876543210987654321098765432109876543210");

Once you have a BigInt, you can perform mathematical operations on it just like you would with a regular number. However, because BigInts can be much larger than regular numbers, some operations may take longer to complete.

It’s important to note that you can’t mix BigInts and regular numbers in the same operation. If you try to do so, you’ll get TypeError.

const bigInt = 1234567890123456789012345678901234567890n;
const regularNum = 42;
const result = bigInt + regularNum;
// TypeError: Cannot mix BigInt and other types, use explicit conversions

ECMAScript 12 Features:

1. Numeric separators:

It allows you to add underscores to numeric literals (integers and floats) to make them more readable.

const number_1 = 1234567890;
console.log(number_1)// Output: 1234567890

const number_2 = 1_234_567_890; // Now its more readable
console.log(number_2)// Output: 1234567890

Numeric separators can also be used with binary, octal, and hexadecimal literals, as well as with BigInts.

const binary = 0b1010_0001_0101_1100;
const octal = 0o7_654_321;
const hex = 0x12_ab_cd_ef;
const bigInt = 123_456_789_012n;

2. Logical assignment operator:

Logical assignment operators are shorthand notations that allow you to combine a logical operator (AND, OR, or XOR) with an assignment in a single statement. The logical assignment operators are &&=, ||=, and ^=.

let x = 5;
x &&= 2;
console.log(x); // 2
let y = null;
y ||= 2;
console.log(y); // 2

These operators can be useful for reducing boilerplate and making your code more concise, but you should be careful not to sacrifice readability for brevity.

ECMAScript 13 Features:

1. Top-level await:

Before ES13 we could only use await inside the async functions. But now, the await keyword can also be used outside the async functions at the top level of a module to wait for a Promise.

So if any child module is using top level await, then its parent module will start execution only when its child module execution is completed.

It’s important to be aware of its limitations and potential drawbacks, such as the potential for blocking execution and the need to handle errors appropriately.

// Before ES13

await Promise.resolve(console.log("Executed Succesfully"))
// SyntaxError: await is only valid in async function

const printMessage = async () => {
await Promise.resolve(console.log("Executed Succesfully"))

printMessage() // Output: Executed Succesfully
// Top level await

await Promise.resolve(console.log("Executed Succesfully"))
// Output: Executed Succesfully

If you like this post and find it helpful you can give me claps and do, follow me😍!!