Top 10 ES6 Features Every Developer Should Know in 2026
Arrow functions, destructuring, spread operator... modern JavaScript is beautiful. Master the syntax that runs the modern web.
The Revolution of JavaScript#
ECMAScript 2015, commonly known as ES6, was the most significant update to the JavaScript language since its inception. It transformed JavaScript from a quirky scripting language into a robust, general-purpose language capable of powering complex enterprise applications.
Even in 2026, understanding these core features is non-negotiable for any frontend or backend developer. They form the foundation of React, Vue, Node.js, and essentially every modern framework.
In this guide, we will dive deep into the features that you will use every single day.
1. Arrow Functions =>#
Arrow functions provided a concise syntax for writing function expressions. But more importantly, they fixed the long-standing headache of the this keyword.
The Syntax Cleanup
Old ES5 Way:
var add = function(a, b) {
return a + b;
};
ES6 Arrow Way:
const add = (a, b) => a + b;
The this Binding
In ES5, this depended on how the function was called. This often led to bugs in callbacks (like event listeners or timers) where this would suddenly become the window object or undefined.
Arrow functions do not have their own this. They inherit this from the parent scope (lexical scoping).
class Timer {
constructor() {
this.seconds = 0;
// Works perfectly because arrow functions preserve 'this'
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
}
2. Destructuring Assignment#
Destructuring allows you to unpack values from arrays or properties from objects into distinct variables. It is heavily used in React (e.g., const { useState } = React).
Object Destructuring
const user = {
id: 42,
name: "Atish",
role: "Admin",
preferences: {
theme: "dark"
}
};
// Extracting properties
const { name, role } = user;
// Extracting nested properties
const { preferences: { theme } } = user;
// Setting default values
const { status = "active" } = user;
Array Destructuring
const coordinates = [10, 20, 30];
const [x, y] = coordinates; // x=10, y=20
3. Template Literals#
Gone are the days of clumsy string concatenation using the + operator. Template literals allow for embedded expressions and multi-line strings.
The Old Nightmare:
var greeting = "Hello " + name + ", you have " + unreadCount + " messages.";
The ES6 Clean Solution:
const greeting = `Hello ${name}, you have ${unreadCount} messages.`;
You can even run logic inside the curly braces:
const status = `User is ${isOnline ? 'Online' : 'Offline'}`;
4. Default Parameters#
In the past, we had to check if a variable was undefined inside the function body. Now, we can define defaults directly in the signature.
function createUser(name, role = "Guest", status = "Active") {
// role is "Guest" if not provided
// status is "Active" if not provided
}
5. The Spread and Rest Operators (...)#
The three dots ... are magical. They can expand an iterable (Spread) or collect multiple arguments into an array (Rest).
Spread (Expanding)
Perfect for merging arrays or objects immutably (a core concept in Redux).
const oldObj = { a: 1, b: 2 };
const newObj = { ...oldObj, c: 3 };
// Result: { a: 1, b: 2, c: 3 }
const numbers = [1, 2, 3];
const moreNumbers = [...numbers, 4, 5];
// Result: [1, 2, 3, 4, 5]
Rest (Collecting)
function sum(...args) {
return args.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3, 4); // 10
6. Modules (Import / Export)#
Before ES6, we relied on libraries like RequireJS or CommonJS (in Node). ES6 standardizes modules.
math.js
export const add = (a, b) => a + b;
export const PI = 3.14159;
export default function calculator() {
console.log(" Calculator loaded");
}
main.js
import calculator, { add, PI } from './math.js';
calculator();
console.log(add(10, 5));
This native modularity enables Tree Shaking (removing unused code) in bundlers like Vite or Webpack.
7. Promises and Async Programming#
ES6 standardized Promise to handle asynchronous operations, replacing "callback hell".
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data Loaded");
}, 1000);
});
};
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
(Note: In ES2017, async/await made this even better, but Promises are the underlying technology.)
8. Classes#
JavaScript is prototype-based, which can be confusing for developers coming from Java or C#. ES6 Classes provide a cleaner syntax for creating objects and inheritance.
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise`);
}
}
class Dog extends Animal {
speak() {
console.log(`${this.name} barks`);
}
}
Under the hood, this is still using prototypes, but the syntax is much easier to manage.
9. Block-Scoped Variables: let and const#
var is function-scoped and can be hoisted, leading to weird behaviors.
let and const are block-scoped (they only exist inside the { } they were defined in).
- Use
constby default. - Use
letonly if you need to reassign the value. - Never use
var.
Test It Yourself#
The best way to learn is to code. Open the WebFiddle Node.js Sandbox and try writing a Class that uses Arrow Functions and Destructuring.
WebFiddle