Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Apply modern ES2020+ JavaScript patterns: modules, async/await, optional chaining, and functional idioms.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: modern-javascript-patterns3description: 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.4---56# Modern JavaScript Patterns78Comprehensive guide for mastering modern JavaScript (ES6+) features, functional programming patterns, and best practices for writing clean, maintainable, and performant code.910## When to Use This Skill1112- Refactoring legacy JavaScript to modern syntax13- Implementing functional programming patterns14- Optimizing JavaScript performance15- Writing maintainable and readable code16- Working with asynchronous operations17- Building modern web applications18- Migrating from callbacks to Promises/async-await19- Implementing data transformation pipelines2021## ES6+ Core Features2223### 1. Arrow Functions2425**Syntax and Use Cases:**2627```javascript28// Traditional function29function add(a, b) {30return a + b;31}3233// Arrow function34const add = (a, b) => a + b;3536// Single parameter (parentheses optional)37const double = (x) => x * 2;3839// No parameters40const getRandom = () => Math.random();4142// Multiple statements (need curly braces)43const processUser = (user) => {44const normalized = user.name.toLowerCase();45return { ...user, name: normalized };46};4748// Returning objects (wrap in parentheses)49const createUser = (name, age) => ({ name, age });50```5152**Lexical 'this' Binding:**5354```javascript55class Counter {56constructor() {57this.count = 0;58}5960// Arrow function preserves 'this' context61increment = () => {62this.count++;63};6465// Traditional function loses 'this' in callbacks66incrementTraditional() {67setTimeout(function () {68this.count++; // 'this' is undefined69}, 1000);70}7172// Arrow function maintains 'this'73incrementArrow() {74setTimeout(() => {75this.count++; // 'this' refers to Counter instance76}, 1000);77}78}79```8081### 2. Destructuring8283**Object Destructuring:**8485```javascript86const user = {87id: 1,88name: "John Doe",89email: "[email protected]",90address: {91city: "New York",92country: "USA",93},94};9596// Basic destructuring97const { name, email } = user;9899// Rename variables100const { name: userName, email: userEmail } = user;101102// Default values103const { age = 25 } = user;104105// Nested destructuring106const {107address: { city, country },108} = user;109110// Rest operator111const { id, ...userWithoutId } = user;112113// Function parameters114function greet({ name, age = 18 }) {115console.log(`Hello ${name}, you are ${age}`);116}117greet(user);118```119120**Array Destructuring:**121122```javascript123const numbers = [1, 2, 3, 4, 5];124125// Basic destructuring126const [first, second] = numbers;127128// Skip elements129const [, , third] = numbers;130131// Rest operator132const [head, ...tail] = numbers;133134// Swapping variables135let a = 1,136b = 2;137[a, b] = [b, a];138139// Function return values140function getCoordinates() {141return [10, 20];142}143const [x, y] = getCoordinates();144145// Default values146const [one, two, three = 0] = [1, 2];147```148149### 3. Spread and Rest Operators150151**Spread Operator:**152153```javascript154// Array spreading155const arr1 = [1, 2, 3];156const arr2 = [4, 5, 6];157const combined = [...arr1, ...arr2];158159// Object spreading160const defaults = { theme: "dark", lang: "en" };161const userPrefs = { theme: "light" };162const settings = { ...defaults, ...userPrefs };163164// Function arguments165const numbers = [1, 2, 3];166Math.max(...numbers);167168// Copying arrays/objects (shallow copy)169const copy = [...arr1];170const objCopy = { ...user };171172// Adding items immutably173const newArr = [...arr1, 4, 5];174const newObj = { ...user, age: 30 };175```176177**Rest Parameters:**178179```javascript180// Collect function arguments181function sum(...numbers) {182return numbers.reduce((total, num) => total + num, 0);183}184sum(1, 2, 3, 4, 5);185186// With regular parameters187function greet(greeting, ...names) {188return `${greeting} ${names.join(", ")}`;189}190greet("Hello", "John", "Jane", "Bob");191192// Object rest193const { id, ...userData } = user;194195// Array rest196const [first, ...rest] = [1, 2, 3, 4, 5];197```198199### 4. Template Literals200201```javascript202// Basic usage203const name = "John";204const greeting = `Hello, ${name}!`;205206// Multi-line strings207const html = `208<div>209<h1>${title}</h1>210<p>${content}</p>211</div>212`;213214// Expression evaluation215const price = 19.99;216const total = `Total: $${(price * 1.2).toFixed(2)}`;217218// Tagged template literals219function highlight(strings, ...values) {220return strings.reduce((result, str, i) => {221const value = values[i] || "";222return result + str + `<mark>${value}</mark>`;223}, "");224}225226const name = "John";227const age = 30;228const html = highlight`Name: ${name}, Age: ${age}`;229// Output: "Name: <mark>John</mark>, Age: <mark>30</mark>"230```231232### 5. Enhanced Object Literals233234```javascript235const name = "John";236const age = 30;237238// Shorthand property names239const user = { name, age };240241// Shorthand method names242const calculator = {243add(a, b) {244return a + b;245},246subtract(a, b) {247return a - b;248},249};250251// Computed property names252const field = "email";253const user = {254name: "John",255[field]: "[email protected]",256[`get${field.charAt(0).toUpperCase()}${field.slice(1)}`]() {257return this[field];258},259};260261// Dynamic property creation262const createUser = (name, ...props) => {263return props.reduce(264(user, [key, value]) => ({265...user,266[key]: value,267}),268{ name },269);270};271272const user = createUser("John", ["age", 30], ["email", "[email protected]"]);273```274275## Asynchronous Patterns276277### 1. Promises278279**Creating and Using Promises:**280281```javascript282// Creating a promise283const fetchUser = (id) => {284return new Promise((resolve, reject) => {285setTimeout(() => {286if (id > 0) {287resolve({ id, name: "John" });288} else {289reject(new Error("Invalid ID"));290}291}, 1000);292});293};294295// Using promises296fetchUser(1)297.then((user) => console.log(user))298.catch((error) => console.error(error))299.finally(() => console.log("Done"));300301// Chaining promises302fetchUser(1)303.then((user) => fetchUserPosts(user.id))304.then((posts) => processPosts(posts))305.then((result) => console.log(result))306.catch((error) => console.error(error));307```308309**Promise Combinators:**310311```javascript312// Promise.all - Wait for all promises313const promises = [fetchUser(1), fetchUser(2), fetchUser(3)];314315Promise.all(promises)316.then((users) => console.log(users))317.catch((error) => console.error("At least one failed:", error));318319// Promise.allSettled - Wait for all, regardless of outcome320Promise.allSettled(promises).then((results) => {321results.forEach((result) => {322if (result.status === "fulfilled") {323console.log("Success:", result.value);324} else {325console.log("Error:", result.reason);326}327});328});329330// Promise.race - First to complete331Promise.race(promises)332.then((winner) => console.log("First:", winner))333.catch((error) => console.error(error));334335// Promise.any - First to succeed336Promise.any(promises)337.then((first) => console.log("First success:", first))338.catch((error) => console.error("All failed:", error));339```340341### 2. Async/Await342343**Basic Usage:**344345```javascript346// Async function always returns a Promise347async function fetchUser(id) {348const response = await fetch(`/api/users/${id}`);349const user = await response.json();350return user;351}352353// Error handling with try/catch354async function getUserData(id) {355try {356const user = await fetchUser(id);357const posts = await fetchUserPosts(user.id);358return { user, posts };359} catch (error) {360console.error("Error fetching data:", error);361throw error;362}363}364365// Sequential vs Parallel execution366async function sequential() {367const user1 = await fetchUser(1); // Wait368const user2 = await fetchUser(2); // Then wait369return [user1, user2];370}371372async function parallel() {373const [user1, user2] = await Promise.all([fetchUser(1), fetchUser(2)]);374return [user1, user2];375}376```377378**Advanced Patterns:**379380```javascript381// Async IIFE382(async () => {383const result = await someAsyncOperation();384console.log(result);385})();386387// Async iteration388async function processUsers(userIds) {389for (const id of userIds) {390const user = await fetchUser(id);391await processUser(user);392}393}394395// Top-level await (ES2022)396const config = await fetch("/config.json").then((r) => r.json());397398// Retry logic399async function fetchWithRetry(url, retries = 3) {400for (let i = 0; i < retries; i++) {401try {402return await fetch(url);403} catch (error) {404if (i === retries - 1) throw error;405await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));406}407}408}409410// Timeout wrapper411async function withTimeout(promise, ms) {412const timeout = new Promise((_, reject) =>413setTimeout(() => reject(new Error("Timeout")), ms),414);415return Promise.race([promise, timeout]);416}417```418419## Functional Programming Patterns420421Functional programming in JavaScript centers on pure functions, immutability, and composable transformations.422423Key topics covered in [references/advanced-patterns.md](references/advanced-patterns.md):424- **Array methods** — `map`, `filter`, `reduce`, `find`, `findIndex`, `some`, `every`, `flatMap`, `Array.from`425- **Higher-order functions** — custom `forEach`/`map`/`filter`, currying, partial application, memoization426- **Composition and piping** — `compose`/`pipe` utilities with practical data transformation examples427- **Pure functions and immutability** — immutable array/object operations, deep cloning with `structuredClone`428429## Modern Class Features430431ES2022 classes support private fields (`#field`), static fields, getters/setters, and private methods. See [references/advanced-patterns.md](references/advanced-patterns.md) for a full example with inheritance.432433## Modules (ES6)434435```javascript436// Named exports437export const PI = 3.14159;438export function add(a, b) { return a + b; }439440// Default export441export default function multiply(a, b) { return a * b; }442443// Import444import multiply, { PI, add } from "./math.js";445446// Dynamic import (code splitting)447const { add } = await import("./math.js");448```449450For re-exports, namespace imports, and conditional dynamic loading see [references/advanced-patterns.md](references/advanced-patterns.md).451452## Iterators and Generators453454Generators (`function*`) and async generators (`async function*`) enable lazy sequences and async pagination. See [references/advanced-patterns.md](references/advanced-patterns.md) for custom iterator, range generator, fibonacci, and `for await...of` examples.455456## Modern Operators457458```javascript459// Optional chaining — safe property access460const city = user?.address?.city;461const result = obj.method?.();462463// Nullish coalescing — default only for null/undefined (not 0 or "")464const value = null ?? "default"; // 'default'465const zero = 0 ?? "default"; // 0466467// Logical assignment468a ??= "default"; // assign if null/undefined469obj.count ||= 1; // assign if falsy470obj.count &&= 2; // assign if truthy471```472473## Performance Optimization474475See [references/advanced-patterns.md](references/advanced-patterns.md) for debounce, throttle, and lazy evaluation with generators.476477## Best Practices4784791. **Use const by default**: Only use let when reassignment is needed4802. **Prefer arrow functions**: Especially for callbacks4813. **Use template literals**: Instead of string concatenation4824. **Destructure objects and arrays**: For cleaner code4835. **Use async/await**: Instead of Promise chains4846. **Avoid mutating data**: Use spread operator and array methods4857. **Use optional chaining**: Prevent "Cannot read property of undefined"4868. **Use nullish coalescing**: For default values4879. **Prefer array methods**: Over traditional loops48810. **Use modules**: For better code organization48911. **Write pure functions**: Easier to test and reason about49012. **Use meaningful variable names**: Self-documenting code49113. **Keep functions small**: Single responsibility principle49214. **Handle errors properly**: Use try/catch with async/await49315. **Use strict mode**: `'use strict'` for better error catching494495For common pitfalls (this binding, promise anti-patterns, memory leaks), see [references/advanced-patterns.md](references/advanced-patterns.md).496