| name | modern-javascript-patterns |
| description | Master ES6+ features including async/await, destructuring, spread operators, arrow functions, promises, modules, iterators, generators, and functional programming patterns for writing clean, efficient JavaScript code. Use when refactoring legacy code, implementing modern patterns, or optimizing JavaScript applications. |
| layer | 1 |
| tech_stack | javascript, typescript |
| topics | es6, async-await, destructuring, spread, arrow-functions, modules, functional |
| depends_on | |
| complements | typescript-advanced-types |
| keywords | async, await, Promise, const, let, arrow, spread, destructure, import, export |
Modern JavaScript Patterns
Master ES6+ features and functional programming for clean, efficient code.
Arrow Functions
// Basic syntax
const add = (a, b) => a + b;
const double = x => x * 2;
const getRandom = () => Math.random();
// Multi-line (need braces)
const processUser = user => {
const normalized = user.name.toLowerCase();
return { ...user, name: normalized };
};
// Returning objects (wrap in parentheses)
const createUser = (name, age) => ({ name, age });
// Lexical 'this' binding
class Counter {
increment = () => { this.count++; }; // 'this' preserved
}
Destructuring
// Object destructuring
const { name, email } = user;
const { name: userName } = user; // Rename
const { age = 25 } = user; // Default value
const { address: { city } } = user; // Nested
const { id, ...userData } = user; // Rest
// Array destructuring
const [first, second] = numbers;
const [, , third] = numbers; // Skip elements
const [head, ...tail] = numbers; // Rest
let [a, b] = [1, 2]; [a, b] = [b, a]; // Swap
// Function parameters
function greet({ name, age = 18 }) {
console.log(`Hello ${name}`);
}
Spread & Rest
// Spread arrays
const combined = [...arr1, ...arr2];
const copy = [...arr1];
// Spread objects
const settings = { ...defaults, ...userPrefs };
const newObj = { ...user, age: 31 };
// Rest parameters
function sum(...numbers) {
return numbers.reduce((total, n) => total + n, 0);
}
Async/Await
// Basic usage
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
return await response.json();
} catch (error) {
console.error('Error:', error);
throw error;
}
}
// Parallel execution
const [user1, user2] = await Promise.all([
fetchUser(1),
fetchUser(2)
]);
// Promise combinators
Promise.all(promises); // Wait for all
Promise.allSettled(promises); // All results, regardless of outcome
Promise.race(promises); // First to complete
Promise.any(promises); // First to succeed
Functional Patterns
Array Methods
const users = [{ id: 1, name: 'John', active: true }, ...];
// Map - Transform
const names = users.map(u => u.name);
// Filter - Select
const activeUsers = users.filter(u => u.active);
// Reduce - Aggregate
const totalAge = users.reduce((sum, u) => sum + u.age, 0);
// Chaining
const result = users
.filter(u => u.active)
.map(u => u.name)
.sort()
.join(', ');
// Other useful methods
users.find(u => u.id === 2); // First match
users.findIndex(u => u.name === 'Jane'); // Index of first match
users.some(u => u.active); // At least one matches
users.every(u => u.age >= 18); // All match
userTags.flatMap(u => u.tags); // Map and flatten
Higher-Order Functions
// Currying
const multiply = a => b => a * b;
const double = multiply(2);
// Memoization
function memoize(fn) {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (!cache.has(key)) cache.set(key, fn(...args));
return cache.get(key);
};
}
// Composition
const pipe = (...fns) => x => fns.reduce((acc, fn) => fn(acc), x);
const compose = (...fns) => x => fns.reduceRight((acc, fn) => fn(acc), x);
Immutability
// Arrays
const withNew = [...arr, newItem]; // Add
const without = arr.filter(x => x !== item); // Remove
const updated = arr.map(x => x.id === id ? { ...x, name } : x);
// Objects
const updated = { ...user, age: 31 }; // Update
const { password, ...safe } = user; // Remove key
Modern Operators
// Optional chaining
const city = user?.address?.city;
const result = obj.method?.();
const first = arr?.[0];
// Nullish coalescing
const value = null ?? 'default'; // 'default'
const value = 0 ?? 'default'; // 0 (not 'default')
// Logical assignment
a ??= 'default'; // a = a ?? 'default'
a ||= 'default'; // a = a || 'default'
a &&= value; // a = a && value
Modules
// Named exports
export const PI = 3.14159;
export function add(a, b) { return a + b; }
// Default export
export default function multiply(a, b) { return a * b; }
// Importing
import multiply, { PI, add } from './math.js';
import * as Math from './math.js';
// Dynamic import
const module = await import('./feature.js');
Performance Patterns
// Debounce
function debounce(fn, delay) {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
}
// Throttle
function throttle(fn, limit) {
let inThrottle;
return (...args) => {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
Best Practices
- Use const by default - Only let when reassignment needed
- Prefer arrow functions - Especially for callbacks
- Use template literals - Instead of concatenation
- Destructure - For cleaner code
- Use async/await - Instead of Promise chains
- Avoid mutation - Use spread operator
- Use optional chaining - Prevent undefined errors
- Use nullish coalescing - For defaults
- Prefer array methods - Over loops
- Write pure functions - Easier to test
Detailed References
For comprehensive patterns, see:
Resources
- MDN Web Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript
- JavaScript.info: https://javascript.info/