DEV Community

Cover image for ECMAScript - A collection of the main new features of each version
Techelopment
Techelopment

Posted on

ECMAScript - A collection of the main new features of each version

Introduction

ECMAScript¹ (or ES ) is the technical specification of a scripting language, standardized and maintained by ECMA International in ECMA-262 and ISO/IEC 16262. The best known implementations of this language (often referred to as dialects) are JavaScript, JScript and ActionScript (for those who remember the old days of Adobe Flash 😎).

The evolution of the UI/UX (User Interface/User eXperience) of websites has contributed to the growth and diffusion of Javascript, making it the language synonymous with client-side development. In 2009, with the introduction of Node.js, Javascript also “invaded” the server-side development sector, becoming — together with Python — the most used language.

In this article I want to show you the main new features introduced in each release of ECMAScript (and consequently in Javascript).

2009 — ECMAScript 5 (ES5)

5️⃣ Strict Mode: Improves error handling and prevents the use of undeclared variables.
— Browser Support: Chrome 13, Firefox 4, Safari 5.1, Edge 12, IE 10

'use strict' ; 
x = 3.14 ; // This will throw an error because x is not declared
Enter fullscreen mode Exit fullscreen mode

5️⃣ Object Methods: New methods for manipulating objects.
— Browser Support: Chrome 5, Firefox 4, Safari 5, Edge 12, IE 9

const obj = {a:1}; 
Object.defineProperty(obj, 'b', {value:2}); 
console.log( Object.keys(obj)); // ["a", "b"]
Enter fullscreen mode Exit fullscreen mode

5️⃣ Array Methods: Methods to iterate and manipulate arrays.
— Browser Support: Chrome 5, Firefox 3.5, Safari 5, Edge 12, IE 9

const arr = [1, 2, 3, 4]; 
const doubled = arr.map( x => x * 2 ); 
console.log(doubled); // [2, 4, 6, 8]
Enter fullscreen mode Exit fullscreen mode

5️⃣ JSON.parse() and JSON.stringify(): JSON format manipulation.
— Browser Support: Chrome 5, Firefox 3.5, Safari 5, Edge 12, IE 9

//String to JSON 
var personString = '{"name":"Alessandra", "age":30}' ; 
var personJSONObj= JSON.parse(personString); 
console.log(personJSONObj.name ); // Outputs: Alexandra 

//JSON to String 
var personJSONObj = {name:"Alessia", age:25}; 
var personString = JSON.stringify(personJSONObj); 
console.log(personString); // Outputs: {"name":"Alessia","age":25}
Enter fullscreen mode Exit fullscreen mode

2015 — ECMAScript 6 (ES6) / ES2015

6️⃣ Let and Const: Block-scoped variable declarations.
— Browser Support: Chrome 49, Firefox 44, Safari 10, Edge 14

let x = 10 ; 
const y = 20 ;
Enter fullscreen mode Exit fullscreen mode

6️⃣ Arrow Functions: Compact syntax for functions.
— Browser Support: Chrome 45, Firefox 22, Safari 10, Edge 12

const  add = (a, b) => a + b; 
console.log(add(2, 3)); // 5
Enter fullscreen mode Exit fullscreen mode

6️⃣ Template Literals: Multi-line strings and interpolation ( NB. the string must be enclosed in quotes

_— Browser Support: Chrome 41, Firefox 34, Safari 9, Edge 12_

```


const name = 'World' ; 
console.log( `Hello, ${name} !` ); // Hello, World!


```
6️⃣ **Classes**: Syntax for defining classes.
_— Browser Support: Chrome 42, Firefox 45, Safari 9, Edge 13_

```


class  Person { 
  constructor ( name ) { 
    this.name = name; 
  } 
  greet() { 
    console.log( `Hello, ${ this.name} ` ); 
  } 
} 
const john = new  Person( 'John' ); 
john.greet(); // Hello, John


```
6️⃣ **Modules**: Import and export modules.
_— Browser Support: Chrome 61, Firefox 60, Safari 10.1, Edge 16_

```


// In file math.js 
export  function  add( a, b ) { 
  return a + b; 
} 

// In another file 
import { add } from  './math.js' ; 
console.log( add(2, 3)); // 5


```
6️⃣ **Promises**: Easier asynchronous management.
_— Browser Support: Chrome 32, Firefox 29, Safari 8, Edge 12_

```


const promise = new  Promise(( resolve, reject ) => { 
  setTimeout(() =>  resolve( 'Done!' ), 1000 ); 
}); 
promised.then( result =>  console.log(result)); // Done!


```

---

### 2016 — ECMAScript 7 (ES7) / ES2016
7️⃣ **Exponentiation Operator**: Exponentiation operator (`**`).
_— Browser Support: Chrome 52, Firefox 52, Safari 10.1, Edge 14_

```


console.log( 2 ** 3 ); // 8


```
7️⃣ **Array.prototype.includes**: Method to check for the presence of an element in an array.
_— Browser Support: Chrome 47, Firefox 43, Safari 9, Edge 14_

```


const arr = [1, 2, 3]; 
console.log(arr.includes(2)); // true


```

---

### 2017 — ECMAScript 8 (ES8) / ES2017
8️⃣ **Async/Await**: Syntax for asynchronous handling based on Promises.
_— Browser Support: Chrome 55, Firefox 52, Safari 10.1, Edge 15_

```


async  function  fetchData() { 
  const response = await  fetch('https://api.example.com/data'); 
  const data = await response.json(); 
  console.log(data); 
} 
fetchData();


```
8️⃣ **Object.entries and Object.values**​​: Methods to get keys and values ​​of an object.
_— Browser Support: Chrome 54, Firefox 47, Safari 10.1, Edge 14_

```


const obj = {a:1, b:2}; 
console.log(Object.entries(obj)); // [["a", 1], ["b", 2]] 
console.log(Object.values(obj)); // [1, 2]


```
8️⃣ **String Padding**: Methods `padStartand` and `padEnd` for padding strings.
_— Browser Support: Chrome 57, Firefox 48, Safari 10.1, Edge 15_

```


console.log('5'.padStart(2, '0')); // "05" 
console.log('5'.padEnd(2, '0')); // "50"


```

---

### 2018 — ECMAScript 9 (ES9) / ES2018
9️⃣ **Rest/Spread Properties**: Object Operators.
_— Browser Support: Chrome 60, Firefox 55, Safari 11, Edge 16_

```


const obj = {a:1, b:2, c:3}; 
const {a, ...rest} = obj; 
console.log(rest); // {b:2, c:3}


```
9️⃣ **Asynchronous Iteration**: Asynchronous iterators with for-await-of.
_— Browser support: Chrome 63, Firefox 57, Safari 12, Edge 79_

```


async  function  process(array) { 
  for await(let item of array) { 
    console.log(item); 
  } 
} 
process([1, 2, 3]);


```
9️⃣ **Promise.finally**: Method to execute code after a Promise completes.
_— Browser Support: Chrome 63, Firefox 58, Safari 11.1, Edge 18_

```


promise
.then(result => console.log(result))then(result =>  console.log(result))
.catch(error => console.error(error))
.finally(() => console.log('Finished'));


```

---

### 2019 — ECMAScript 10 (ES10) / ES2019
1️⃣0️⃣ **Array.prototype.flat and flatMap**: `flat()` “flattens” an array of arrays into a single array. `flatMap()` combines mapping and flattening.
_— Browser Support: Chrome 69, Firefox 62, Safari 12, Edge 79_

```


const arr = [1, [2, 3], [4, 5]]; 
console.log(arr.flat()); // [1, 2, 3, 4, 5] 

const arr2 = [1, 2, 3]; 
console.log(arr2.flatMap(x => [x, x * 2])); // [1, 2, 2, 4, 3, 6]


```
1️⃣0️⃣ **Object.fromEntries**: Method to create objects from arrays of key-value pairs.
_— Browser Support: Chrome 73, Firefox 63, Safari 12.1, Edge 79_

```


const entries = [['a', 1], ['b', 2]]; 
const obj = Object.fromEntries(entries); 
console.log(obj); // {a:1, b:2}


```
1️⃣0️⃣ **Optional Catch Binding**: Ability to omit the catch parameter in errors.
_— Browser Support: Chrome 66, Firefox 58, Safari 11, Edge 79_

```


try { 
  throw  new  Error( 'Oops' ); 
} catch { //you used to have to write catch(e) 
  console.log('Error caught'); 
}


```

---

### 2020 — ECMAScript 11 (ES11) / ES2020
1️⃣1️⃣ **BigInt**: Data type to represent very large integers.
_— Browser Support: Chrome 67, Firefox 68, Safari 14, Edge 79_

```


const bigInt = 1234567890123456789012345678901234567890n ; 
console.log(bigInt); // 1234567890123456789012345678901234567890n


```
1️⃣1️⃣ **Optional Chaining (?.)**: Allows you to access deeply nested properties without having to explicitly check whether each reference in the chain is null or undefined.
_— Browser Support: Chrome 80, Firefox 74, Safari 13.1, Edge 80_

```


let user = {name:"Alice", address: {city:"Wonderland"}}; 
console.log(user?.address?.city ); // "Wonderland" 
console.log(user?.contact?.phone ); // undefined


```
1️⃣1️⃣ **Nullish Coalescing Operator (??)**: Returns the value of its right operand when the left operand is null or undefined.
_— Browser Support: Chrome 80, Firefox 72, Safari 13.1, Edge 80_

```


let foo = null ?? 'default string' ; 
console.log(foo); // "default string"


```
1️⃣1️⃣ **Dynamic Import**: Allows you to load modules dynamically, i.e. during code execution, rather than statically at the beginning. This is useful for conditional module loading or module loading. Dynamic Import is particularly useful for improving the performance of web applications, allowing you to load only the necessary code when needed.
_— Browser Support: Chrome 63, Firefox 67, Safari 11.1, Edge 79_

```


// Suppose we have a module called 'module.js' 
// module.js 
export  function  greet() { 
  console.log("Hello from the module!"); 
} 

// Main code 
async  function  loadModule() { 
  const  module = await  import('./module.js'); 
  module.greet(); // "Hello from the module!"
 } 

loadModule();


```

---

### 2021 — ECMAScript 12 (ES12) / ES2021
1️⃣2️⃣ **Logical Assignment Operators (&&=, ||=, ??=)**: Combines logical operators with assignment.
_— Browser Support : Chrome 85, Firefox 79, Safari 14, Edge 85_

```


let a = 1 ; 
to &&= 2 ; 
console.log(a); // 2 

let b = null ; 
b ??= 3 ; 
console.log(b); // 3


```
1️⃣2️⃣ **String.prototype.replaceAll()**: Replaces all occurrences of a string with another.
_— Browser Support : Chrome 85, Firefox 77, Safari 13.1, Edge 85_

```


let str = "Hello world! Hello!" ; 
console.log(str.replaceAll("Hello", "Hi")); // "Hi world! Hi!"


```
1️⃣2️⃣ **Numeric Separators**: Improves the readability of large numbers by adding underscores ( _ ) as separators.
_— Browser Support : Chrome 75, Firefox 70, Safari 13, Edge 79_

```


let largeNumber = 1_000_000_000 ; 
console.log(largeNumber); // 1000000000


```
1️⃣2️⃣ **Promise.any()**: Returns a promise that resolves as soon as one of the provided promises resolves, or rejects if all promises are rejected.
_— Browser Support : Chrome 85, Firefox 79, Safari 14.1, Edge 85_

```


const p1 = Promise.reject('Error'); 
const p2 = new  Promise((resolve) => setTimeout(resolve, 100, 'Success' )); 
const p3 = new  Promise((resolve) => setTimeout(resolve, 200, 'Another Success')); 

Promise.any([p1, p2, p3]).then((value) => { 
  console.log(value); // "Success"
 });


```
1️⃣2️⃣ **WeakRefs**: Allows you to create weak references to objects, which do not prevent garbage collection.
_— Browser Support : Chrome 84, Firefox 79, Safari 14, Edge 84_

```


let obj = {name:'Alice'}; 
let weakRef = new  WeakRef(obj); 

obj = null ; // Object can be garbage collected 
console.log(weakRef.deref()); // May return undefined if object was garbage collected


```
1️⃣2️⃣ **FinalizationRegistry**: Allows you to register callbacks that are executed when a registered object is garbage collected.
_— Browser Support : Chrome 84, Firefox 79, Safari 14, Edge 84_

```


let registry = new  FinalizationRegistry((heldValue ) => { 
  console.log(`Object with held value ${heldValue} was garbage collected`); 
}); 

let obj = {name:'Alice'}; 
registry.register(obj, 'some value' ); 

obj = null ; // The object can be collected by the garbage collector


```

---

### 2022 — ECMAScript 13 (ES13) / ES2022
1️⃣3️⃣ **Top-level await**: Allows you to use awaitoutside of the functions async.
_— Browser Support: Chrome 89, Firefox 89, Safari 15, Edge 89_

```


// In a module 
let response = await  fetch('https://api.example.com/data' ); 
let data = await response.json(); 
console.log(data);


```
1️⃣3️⃣ **Class Fields**: Allows you to define properties directly within a class definition.
_— Browser Support: Chrome 72, Firefox 90, Safari 14.1, Edge 79_

```


class  MyClass { 
  myField = 'value' ; 
} 
let instance = new  MyClass(); 
console.log(instance.myField ); // "value"


```
1️⃣3️⃣ **Static Class Fields and Private Methods**: Support for static fields and private methods in classes.
_— Browser Support: Supported by Chrome 72+, Firefox 90+, Edge 79+, Safari 14+._

```


class  MyClass { 
  static staticField = 'static' ; 
  # privateMethod() { 
    return  'private method' ; 
  } 

  callPrivateMethod() { 
    return  this.#privateMethod(); 
  } 
} 

console.log(MyClass.staticField); // 'static' 
const instance = new  MyClass(); 
console.log(instance.callPrivateMethod()); // 'private method'


```
1️⃣3️⃣ **RegExp Match Indices**: Adding property indicesto objects RegExp.
_— Browser Support: Supported by Chrome 90+, Firefox 90+, Edge 90+, Safari 15+._

```


const regex = /a(b)c/ ; 
const match = regex.exec('abc'); 
console.log(match.indices); // [[0, 3], [1, 2]]


```
1️⃣3️⃣ **Object.hasOwn()**: A safer way to check if an object owns a specific property.
_— Browser Support: Supported by Chrome 93+, Firefox 92+, Edge 93+, Safari 15+._

```


const obj = {key:'value'}; 
console.log(Object.hasOwn(obj, 'key')); // true


```

---

### 2023 — ECMAScript 14 (ES14) / ES2023
1️⃣4️⃣ **Array.prototype.toSorted**: This method works like Array.prototype.sort, but creates a new sorted array without modifying the original array.
_— Browser Support: Supported by Chrome 110+, Firefox 115+, Edge 110+, Safari 16+._

```


const arr = [3, 1, 4, 1, 5]; 
const sortedArr = arr.toSorted(); 
console.log(sortedArr); // [1, 1, 3, 4, 5] 
console.log(arr); // [3, 1, 4, 1, 5]


```
1️⃣4️⃣ **Array.prototype.toReversed**: Similar to Array.prototype.reverse, but creates a new reversed array without modifying the original array.
_— Browser Support: Supported by Chrome 110+, Firefox 115+, Edge 110+, Safari 16+._

```


const arr = [1, 2, 3]; 
const reversedArr = arr.toReversed(); 
console.log(reversedArr); // [3, 2, 1] 
console.log(arr); // [1, 2, 3]


```
1️⃣4️⃣ **Array.prototype.toSpliced**: Allows you to create a new array with some elements removed or replaced, without modifying the original array.
_— Browser Support: Supported by Chrome 110+, Firefox 115+, Edge 110+, Safari 16+._

```


const arr = [1, 2, 3, 4]; 
const splicedArr = arr.toSpliced​​(1, 2, 5, 6); 
console.log(splicedArr); // [1, 5, 6, 4] 
console.log(arr); // [1, 2, 3, 4]


```
1️⃣4️⃣ **Array.prototype.with**: Creates a new array with a modified element at the specified index.
_— Browser Support: Supported by Chrome 110+, Firefox 115+, Edge 110+, Safari 16+._

```


const arr = [1, 2, 3]; 
const newArr = arr.with(1, 4); 
console.log(newArr); // [1, 4, 3] 
console.log(arr); // [1, 2, 3]


```
1️⃣4️⃣ **Hashbang syntax support (#!)**: Allows you to use hashbang syntax in JavaScript files to specify the interpreter.
_— Browser support: Not applicable to browsers, but supported in Node.js environments._

```


#!/usr/bin/env node 
console.log('Hello, world!');


```

---

### 2024 — ECMAScript 15 (ES15) / ES2024
1️⃣5️⃣ **Object.groupBy**: is a function that allows you to group elements of an array based on a criterion specified by a callback function. It returns an object whose properties correspond to the groups created by the function.
_— Browser Support: Supported by Chrome 117+, Firefox 119+, Edge 117+, Safari 17.4+._

```


const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 

const grouped = Object.groupBy(numbers, num => num % 2 === 0 ? 'even' : 'odd'); 

console.log(grouped); // Output: { odd: [1, 3, 5, 7, 9], even: [2, 4, 6, 8]}


```
1️⃣5️⃣ **Promise.withResolvers**: Facilitates the creation of promises that can be resolved or rejected from the outside. Provides an object that contains a promise(promise) along with functions to resolve(resolve) or reject(reject) it.

Previously, the pattern for creating external promises was a bit verbose and not very clear. `Promise.withResolvers`simplifies this process, making it easier to manage promises in complex scenarios such as handling timeouts, external resources, or other asynchronous conditions.

_— Browser Support: Supported by Chrome 119+, Firefox 121+, Edge 119+, Safari 17.4+._

To better understand this new feature we must first take a step back to ES13. We will use the following code as an example to understand the benefits of `Promise.withResolvers`:

```


// ES14 - ES2023 
let resolveFn, rejectFn; 

const promise = new  Promise((resolve, reject) => { 
  resolveFn = resolve; 
  rejectFn = reject; 
}); 

setTimeout(() => resolveFn('Resolved after 1 second' ), 1000); 

promised.then(value => console.log(value)); 
// Output after 1 second: "Resolved after 1 second"


```

With `Promise.withResolvers`, we can do the same thing more simply:

```


const {promise, resolve, reject} = Promise.withResolvers(); 

setTimeout(() =>  resolve('Resolved after 1 second' ), 1000); 

promised.then(value => console.log(value)); 
// Output after 1 second: "Resolved after 1 second"


```
Another example to better understand its use:

```


function  wait(ms) { 
  const {promise, resolve, reject} = Promise.withResolvers(); 

  // Resolve the promise after the specified number of milliseconds 
  setTimeout(() => { 
    resolve(`Resolved after ${ms} milliseconds`); 
  }, ms); 

  return promise; 
} 

// Use the 'wait' function and wait for the promise to be resolved 
wait(2000).then((message) => console.log(message)); 
// Output after 2 seconds: "Resolved after 2000 milliseconds"


```

---

## Before we leave, here are some interesting proposals that we might see in the future…

> NB The features listed below are still in the Proposal stage

**Decorators**: New possibilities for using decorators with a clearer and more powerful syntax as `@login` this example.

> Decorators use a syntax to add annotations or modify the behavior of classes, methods, properties, and parameters. In ES15, decorators are improved to provide clearer syntax and more power.

```


function  log(target, key, descriptor) { 
  const originalMethod = descriptor.value ; 
  descriptor.value = function(...args ) { 
    console.log(`Calling ${key} with`, args); 
    return originalMethod.apply(this, args); 
  }; 
  return descriptor; 
} 

class  MyClass { 
  @log 
  myMethod(arg) { 
    console.log(`Inside myMethod with ${arg} `); 
  } 
} 

const instance = new  MyClass(); 
instance.myMethod('test');
#Output
 Calling myMethod with test
 Inside myMethod with test


```
**Records and Tuples**: New immutable data types that offer significant advantages in manipulating and managing data structures. These types are designed to be more predictable and efficient, especially in scenarios where immutability is desirable.

```


const record = #{name:"Alice", age:30}; 

console.log(record.name); // Alice 
console.log(record.age);   // 30 

// Attempt to edit throws error 
// record.name = "Bob"; // TypeError: Cannot assign to read only property 'name' of object 


const tuple = #[1, 2, 3]; 

console.log(tuple[0]); // 1 
console.log(tuple[1]); // 2 
consoles.log(tuple[2]); // 3 

// Attempt to modify throws error 
// tuple[0] = 10; // TypeError: Cannot assign to read only property '0' of object


```
**Pipeline Operator**: is an operator that allows you to take the output of an expression and pass it as input to the next function. This approach improves the readability of the code when you have multiple subsequent operations that need to be applied to a value.

The operator `|>` is used to apply a function to a value, passing the value as the first argument to the function.


```


function  add(x, y) { 
  return x + y; 
} 

function  multiply(x, y) { 
  return x * y; 
} 

function  square(x) { 
  return x * x; 
} 

/** Example 1 with functions **/ 
const result = 5
   |> (x =>  add(x, 3)) //5 + 3
   |> (x =>  multiply(x, 2)) //(5 + 3) * 2
   |> square; //((5 + 3) * 2) ^ 2 

console.log(result); // 128 


/** Example 2 with array **/ 
const numbers = [1, 2, 3, 4, 5]; 

const result = numbers 
  |> (arr => arr.map( x => x * 2 )) // [2, 4, 6, 8, 10]
   |> (arr => arr.filter( x => x > 5 )); // [6, 8, 10] 

console.log(result); // [6, 8, 10]


```



---
## Follow me #techelopment
Medium: [@techelopment](https://medium.com/@techelopment)
Dev.to: [Techelopment](https://dev.to/techelopment)
facebook: [Techelopment](https://www.facebook.com/techelopment)
instagram: [@techelopment](https://instagram.com/techelopment)
X: [techelopment](https://twitter.com/techelopment)
telegram: [techelopment_channel](https://t.me/techelopment_channel)
youtube: [@techelopment](https://youtube.com/@techelopment)
whatsapp: [Techelopment](https://whatsapp.com/channel/0029VaoJHA1Lo4hkXn1rcn3y)

---

## References
[1] [ECMAScript - Wikipedia](https://it.wikipedia.org/wiki/ECMAScript)
[GitHub - sudheerj/ECMAScript-features: ECMAScript features cheatsheet](https://github.com/sudheerj/ECMAScript-features)
[Modern JavaScript Features in ES13 ES2022](https://dev.to/digitalpollution/embracing-modern-javascript-features-in-es13-es2022-3dde)
[JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
[V8](https://v8.dev)
[Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/)
[Javascript — What's new with ECMAScript® 2024 (ES15)](https://medium.com/@yourfuse/javascript-whats-new-with-ecmascript-2024-es15-ef056d2f4bf1)
[⭐ECMAScript version history - Wikipedia](https://en.wikipedia.org/wiki/ECMAScript_version_history)
[⭐proposals/finished-proposals.md at main · tc39/proposals](https://github.com/tc39/proposals/blob/main/finished-proposals.md)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)