Modern JS (ES6+)
Let/const, arrow functions, destructuring
Modern JavaScript (ES6+)
ES6 (ECMAScript 2015) and later versions introduced many features that make JavaScript more powerful and enjoyable to write. Here are the essential modern features every developer should know.
Template Literals
String interpolation and multi-line strings:
// Old way
const name = 'Alice';
const greeting = 'Hello, ' + name + '!';
// ES6 way
const greeting = `Hello, ${name}!`;
// Multi-line
const html = `
${name}
Welcome back!
`;
// Expressions inside
const price = 10;
const tax = 1.5;
console.log(`Total: $${price + tax}`); // "Total: $11.5"
Destructuring
// Array destructuring
const colors = ['red', 'green', 'blue'];
const [first, second] = colors;
console.log(first); // "red"
console.log(second); // "green"
// Skip elements
const [, , third] = colors;
console.log(third); // "blue"
// Rest operator
const [head, ...tail] = colors;
console.log(head); // "red"
console.log(tail); // ["green", "blue"]
// Object destructuring
const user = { name: 'Alice', age: 30, city: 'NYC' };
const { name, age } = user;
console.log(name); // "Alice"
// Rename while destructuring
const { name: userName } = user;
console.log(userName); // "Alice"
// Default values
const { country = 'USA' } = user;
console.log(country); // "USA"
// Function parameters
function greet({ name, age }) {
console.log(`Hello ${name}, age ${age}`);
}
greet(user); // "Hello Alice, age 30"
Spread & Rest Operators
// Spread: Expand array/object
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Copy array
const copy = [...arr1]; // New array, not reference
// Spread in function calls
const numbers = [1, 5, 3, 8, 2];
console.log(Math.max(...numbers)); // 8
// Object spread
const user = { name: 'Alice', age: 30 };
const updatedUser = { ...user, age: 31, city: 'NYC' };
// { name: 'Alice', age: 31, city: 'NYC' }
// Rest: Collect remaining items
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
Default Parameters
// Old way
function greet(name) {
name = name || 'Guest';
console.log(`Hello, ${name}`);
}
// ES6 way
function greet(name = 'Guest') {
console.log(`Hello, ${name}`);
}
greet(); // "Hello, Guest"
greet('Alice'); // "Hello, Alice"
// Works with objects too
function createUser({ name = 'Anonymous', role = 'user' } = {}) {
return { name, role };
}
Enhanced Object Literals
const name = 'Alice';
const age = 30;
// Property shorthand
const user = { name, age }; // Same as { name: name, age: age }
// Method shorthand
const obj = {
// Old way
sayHi: function() {
console.log('Hi');
},
// New way
sayHello() {
console.log('Hello');
}
};
// Computed property names
const key = 'favoriteColor';
const obj2 = {
[key]: 'blue',
[`${key}_secondary`]: 'green'
};
Classes
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, I'm ${this.name}`;
}
get birthYear() {
return new Date().getFullYear() - this.age;
}
static species() {
return 'Homo sapiens';
}
}
// Inheritance
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
return `${this.name} is studying`;
}
}
const alice = new Student('Alice', 20, 'A');
console.log(alice.greet()); // "Hello, I'm Alice"
console.log(alice.study()); // "Alice is studying"
Array Methods
const numbers = [1, 2, 3, 4, 5];
// find & findIndex
const found = numbers.find(n => n > 3); // 4
const index = numbers.findIndex(n => n > 3); // 3
// includes
numbers.includes(3); // true
numbers.includes(10); // false
// Array.from (create array from iterable)
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
Array.from({ length: 5 }, (_, i) => i); // [0, 1, 2, 3, 4]
// Array.of (create array from arguments)
Array.of(1, 2, 3); // [1, 2, 3]
// flat & flatMap
const nested = [1, [2, 3], [4, [5]]];
nested.flat(); // [1, 2, 3, 4, [5]]
nested.flat(2); // [1, 2, 3, 4, 5]
const arr = [1, 2, 3];
arr.flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]
Promises & Async/Await
// Promise
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('Data loaded'), 1000);
});
};
fetchData()
.then(data => console.log(data))
.catch(error => console.error(error));
// Async/Await (cleaner!)
async function getData() {
try {
const data = await fetchData();
console.log(data);
} catch (error) {
console.error(error);
}
}
// Parallel async operations
async function getMultiple() {
const [users, posts] = await Promise.all([
fetch('/api/users').then(r => r.json()),
fetch('/api/posts').then(r => r.json())
]);
return { users, posts };
}
Optional Chaining & Nullish Coalescing
const user = {
name: 'Alice',
address: {
city: 'NYC'
}
};
// Optional chaining (?.)
console.log(user.address?.city); // "NYC"
console.log(user.address?.country); // undefined (no error)
console.log(user.profile?.bio); // undefined (safe!)
// With arrays
const users = null;
console.log(users?.[0]); // undefined
// With functions
const greet = null;
greet?.(); // undefined (doesn't throw)
// Nullish coalescing (??)
const value = null ?? 'default'; // "default"
const zero = 0 ?? 'default'; // 0 (not "default"!)
// Difference from ||
console.log(0 || 10); // 10 (0 is falsy)
console.log(0 ?? 10); // 0 (0 is not null/undefined)
Map & Set
// Map (better than objects for key-value storage)
const map = new Map();
map.set('name', 'Alice');
map.set('age', 30);
console.log(map.get('name')); // "Alice"
console.log(map.has('age')); // true
console.log(map.size); // 2
map.delete('age');
// Iterate
for (const [key, value] of map) {
console.log(key, value);
}
// Set (unique values only)
const set = new Set([1, 2, 3, 2, 1]);
console.log(set); // Set {1, 2, 3}
set.add(4);
set.delete(1);
console.log(set.has(2)); // true
console.log(set.size); // 3
// Remove duplicates from array
const arr = [1, 2, 2, 3, 3, 3, 4];
const unique = [...new Set(arr)]; // [1, 2, 3, 4]
✨ More Modern Features
- • BigInt: For integers larger than 2^53 - 1
- • Symbol: Unique identifiers
- • Proxy: Intercept object operations
- • Reflect: Low-level object operations
- • WeakMap/WeakSet: Garbage-collectable collections
✓ When to Use Modern Features
- • Use them! They're widely supported in modern browsers
- • For older browser support, use transpilers like Babel
- • Template literals make string building much cleaner
- • Destructuring reduces boilerplate code
- • Async/await is the preferred way to handle promises
- • Arrow functions are great for callbacks