JavaScript ES6+ Modern Features
ECMAScript 2015 (ES6) and its subsequent yearly updates introduced a large number of features that transformed how JavaScript is written. This topic provides a comprehensive reference of all the major modern JavaScript features introduced from ES6 onward.
ES6 (ECMAScript 2015)
let and const
let counter = 0; // Block-scoped, reassignable
const MAX_VAL = 100; // Block-scoped, constantArrow Functions
const double = n => n * 2;
const add = (a, b) => a + b;
const greet = name => `Hello, ${name}!`;Template Literals
let name = "Ritika";
let age = 22;
console.log(`${name} is ${age} years old.`);Destructuring
// Array destructuring
let [a, b, c] = [10, 20, 30];
// Object destructuring
let { name, city = "Unknown" } = { name: "Priya" };
// In function parameters
function show({ name, age }) {
console.log(`${name}, ${age}`);
}Default Parameters
function greet(name = "Guest") {
console.log("Hello, " + name);
}Spread and Rest Operators
// Spread — expand
let arr = [1, 2, 3];
let newArr = [...arr, 4, 5];
// Rest — collect
function sum(...nums) {
return nums.reduce((t, n) => t + n, 0);
}Classes
class Animal {
constructor(name) { this.name = name; }
speak() { console.log(`${this.name} speaks.`); }
}
class Dog extends Animal {
speak() { console.log(`${this.name} barks!`); }
}Modules (import/export)
// Export
export const PI = 3.14;
export function area(r) { return PI * r * r; }
export default class Circle {}
// Import
import Circle, { PI, area } from "./shapes.js";Promises
let p = new Promise((resolve, reject) => {
setTimeout(() => resolve("Done!"), 1000);
});
p.then(result => console.log(result))
.catch(err => console.error(err));Map and Set
let map = new Map([["a", 1], ["b", 2]]);
let set = new Set([1, 2, 2, 3, 3]);Symbol
let id = Symbol("id");
let obj = { [id]: 42 };
console.log(obj[id]); // 42for...of Loop
for (let item of ["X", "Y", "Z"]) {
console.log(item);
}Iterators and Generators
function* gen() {
yield 1;
yield 2;
yield 3;
}Proxy and Reflect
let proxy = new Proxy({}, {
get(target, key) { return key in target ? target[key] : "Not found"; }
});ES2016 (ES7)
Array.prototype.includes()
let fruits = ["apple", "mango", "banana"];
console.log(fruits.includes("mango")); // true
console.log(fruits.includes("grape")); // falseExponentiation Operator (**)
console.log(2 ** 10); // 1024
console.log(3 ** 3); // 27ES2017 (ES8)
async/await
async function loadData() {
try {
let res = await fetch("https://api.example.com/data");
let data = await res.json();
console.log(data);
} catch (err) {
console.log(err);
}
}Object.entries() and Object.values()
let obj = { a: 1, b: 2, c: 3 };
console.log(Object.entries(obj)); // [["a",1],["b",2],["c",3]]
console.log(Object.values(obj)); // [1, 2, 3]String.prototype.padStart() and padEnd()
console.log("7".padStart(3, "0")); // "007"
console.log("5".padEnd(5, "-")); // "5----"Object.getOwnPropertyDescriptors()
let descriptors = Object.getOwnPropertyDescriptors({ name: "Raj" });
console.log(descriptors.name.writable); // trueES2018 (ES9)
Spread and Rest for Objects
let original = { a: 1, b: 2 };
let copy = { ...original, c: 3 };
function show({ a, ...rest }) {
console.log(a, rest); // 1, { b: 2, c: 3 }
}
show(copy);Promise.finally()
fetch("/api")
.then(res => res.json())
.catch(err => console.log(err))
.finally(() => console.log("Always runs"));Asynchronous Iteration (for await...of)
async function processStream(asyncIterable) {
for await (let chunk of asyncIterable) {
console.log(chunk);
}
}ES2019 (ES10)
Array.prototype.flat() and flatMap()
let nested = [1, [2, [3, [4]]]];
console.log(nested.flat(Infinity)); // [1, 2, 3, 4]
let words = ["hello world", "foo bar"];
console.log(words.flatMap(w => w.split(" "))); // ["hello","world","foo","bar"]Object.fromEntries()
let entries = [["name", "Asha"], ["age", 25]];
let obj = Object.fromEntries(entries);
console.log(obj); // { name: "Asha", age: 25 }String.prototype.trimStart() and trimEnd()
console.log(" hello ".trimStart()); // "hello "
console.log(" hello ".trimEnd()); // " hello"Optional catch Binding
// No need to name the error if not using it
try {
JSON.parse("{invalid}");
} catch {
console.log("Parse failed.");
}ES2020 (ES11)
Optional Chaining (?.)
let user = { address: { city: "Pune" } };
console.log(user?.address?.city); // Pune
console.log(user?.phone?.number); // undefined (no error!)
// Works with methods too
console.log(user?.getName?.()); // undefined (no error!)Nullish Coalescing Operator (??)
let setting = null;
let theme = setting ?? "light"; // "light" (fallback for null/undefined only)
console.log(theme);
// Difference from || — ?? only triggers on null/undefined, not 0 or ""
let count = 0;
console.log(count || 10); // 10 (0 is falsy)
console.log(count ?? 10); // 0 (0 is not null/undefined)Promise.allSettled()
let results = await Promise.allSettled([
Promise.resolve("OK"),
Promise.reject("Error"),
Promise.resolve("Also OK")
]);
results.forEach(r => console.log(r.status, r.value || r.reason));BigInt
let bigNum = 9007199254740991n;
console.log(bigNum + 1n); // 9007199254740992nglobalThis
console.log(globalThis); // window in browsers, global in Node.jsES2021 (ES12)
Logical Assignment Operators
let a = null;
a ??= "default"; // Assign only if a is null/undefined
console.log(a); // "default"
let b = 0;
b ||= 100; // Assign only if b is falsy
console.log(b); // 100
let c = 5;
c &&= 10; // Assign only if c is truthy
console.log(c); // 10String.prototype.replaceAll()
let text = "cat and cat and cat";
console.log(text.replaceAll("cat", "dog")); // "dog and dog and dog"Promise.any()
let first = await Promise.any([
Promise.reject("Fail 1"),
Promise.resolve("Success!"),
Promise.reject("Fail 2")
]);
console.log(first); // "Success!"ES2022 (ES13)
Top-Level await (in modules)
// In a module file — no async function wrapper needed
let data = await fetch("https://api.example.com").then(r => r.json());
console.log(data);Class Private Fields and Methods (#)
class User {
#password;
constructor(pass) { this.#password = pass; }
check(input) { return input === this.#password; }
}Array.prototype.at()
let arr = [10, 20, 30, 40, 50];
console.log(arr.at(0)); // 10 (first element)
console.log(arr.at(-1)); // 50 (last element)
console.log(arr.at(-2)); // 40 (second from last)Object.hasOwn()
let obj = { city: "Delhi" };
console.log(Object.hasOwn(obj, "city")); // true
console.log(Object.hasOwn(obj, "state")); // falseES2023 (ES14)
Array findLast() and findLastIndex()
let scores = [40, 85, 60, 90, 55];
console.log(scores.findLast(n => n > 80)); // 90
console.log(scores.findLastIndex(n => n > 80)); // 3Array toSorted(), toReversed(), toSpliced(), with()
let arr = [3, 1, 2];
let sorted = arr.toSorted(); // [1, 2, 3] — original unchanged
let reversed = arr.toReversed(); // [2, 1, 3] — original unchanged
let updated = arr.with(1, 99); // [3, 99, 2] — original unchangedModern Feature Quick Reference Table
| Feature | Version | Summary |
|---|---|---|
| let/const | ES6 | Block-scoped variable declarations |
| Arrow functions | ES6 | Short function syntax with lexical this |
| Template literals | ES6 | String interpolation with backticks |
| Destructuring | ES6 | Unpack arrays and objects into variables |
| Spread / Rest | ES6 | Expand / collect values with ... |
| Classes | ES6 | OOP syntax built on prototypes |
| Modules | ES6 | import / export for code splitting |
| Promises | ES6 | Handle async results cleanly |
| async/await | ES8 | Write async code like sync |
| Optional chaining | ES11 | Safe access to nested properties (?.) |
| Nullish coalescing | ES11 | Fallback for null/undefined (??) |
| Private fields | ES13 | Truly private class members (#) |
| Array.at() | ES13 | Access elements from end with negative index |
Key Points to Remember
- ES6 (2015) was the largest JavaScript update — it introduced classes, modules, promises, arrow functions, and destructuring
- Optional chaining
?.prevents TypeErrors when accessing nested properties on null/undefined - Nullish coalescing
??provides a fallback only fornullandundefined— not for 0 or empty string - Logical assignment operators (
??=,||=,&&=) combine checks with assignment - Non-mutating array methods (
toSorted(),toReversed(),with()) return new arrays without modifying the original - Private class fields with
#provide true encapsulation in ES2022+ - Always prefer modern features when targeting current browsers — they are more expressive and safer
