modern-javascript-patterns
Skill2 starsChanged 8 months agoMITView on GitHub
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.
6 other projects use a version of this, 6 of them edited.
Adopted by
Most recently taken up by
- xfstudio/skillsedited, first seen Oct 13, 2026
- Samueladewole/claude-skillsedited, first seen Oct 13, 2026
- NorkzYT/claude-code-autopilotedited, first seen Jun 11, 2026
- SuarezPM/Apohara-Catalystedited, first seen May 12, 2026
- GPTtang/skill-atlasedited, first seen Mar 22, 2026
- ai4brands-design/claude-skillsedited, first seen Mar 22, 2026
Other versions6 projects use a version of this.
Word for word · 0
None found.
Edited · 6
- xfstudio/skills★ 957% same
- GPTtang/skill-atlas★ 499% same
- ai4brands-design/claude-skills★ 257% same
- NorkzYT/claude-code-autopilot★ 299% same
- SuarezPM/Apohara-Catalyst★ 182% same
- Samueladewole/claude-skills★ 099% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository239 other files it gives its agents.
- claude-code-docs/agents.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- claude-code-docs/llms.txtllms.txt
- agent-native-architectureSkill
- claude-apiSkill
- embedding-strategiesSkill
- fal-ai-mediaSkill
- gemini-imagegenSkill
- hybrid-search-implementationSkill
- langchain-architectureSkill
- llm-evaluationSkill
- ml-pipeline-workflowSkill
- prompt-engineering-patternsSkill
- rag-implementationSkill
- similarity-search-patternsSkill
- vector-index-tuningSkill
- api-design-principlesSkill
- api-designSkill
- architecture-patternsSkill
- cqrs-implementationSkill
- event-store-designSkill
- fastapi-templatesSkill
- microservices-patternsSkill
- openapi-spec-generationSkill
- projection-patternsSkill
- saga-orchestrationSkill
- api-conventionsSkill
- andrew-kane-gem-writerSkill
- angular-migrationSkill
- auth-implementation-patternsSkill
- backend-patternsSkill
- bazel-build-optimizationSkill
- coding-standardsSkill
- database-migrationSkill
- debugging-strategiesSkill
- dependency-upgradeSkill
- dhh-rails-styleSkill
- dotnet-backend-patternsSkill
- dspy-rubySkill
- error-handling-patternsSkill
- monorepo-managementSkill
- nodejs-backend-patternsSkill
- nx-workspace-patternsSkill
- react-modernizationSkill
- temporal-python-testingSkill
- turborepo-cachingSkill
- workflow-orchestration-patternsSkill
- defi-protocol-templatesSkill
- nft-standardsSkill
- solidity-securitySkill
- web3-testingSkill
- backtesting-frameworksSkill
- billing-automationSkill
- competitive-landscapeSkill
- data-storytellingSkill
- employment-contract-templatesSkill
- investor-materialsSkill
- investor-outreachSkill
- kpi-dashboard-designSkill
- market-sizing-analysisSkill
- The first 60 shown.
The file
We split this skill into the rules it gives an agent
11 rules. 5 are common, 6 are distinctive, and 0 are very specific to this project.
5
Common
Most of the 6 edited versions we read keep these.
6
Distinctive
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Common: line 894
Use const by default: Only use let when reassignment is needed
- Common: line 896
Use template literals: Instead of string concatenation
- Common: line 898
Use async/await: Instead of Promise chains
- Common: line 899
Avoid mutating data: Use spread operator and array methods
- Common: line 907
Handle errors properly: Use try/catch with async/await
- Distinctive: line 912
this binding confusion: Use arrow functions or bind()
- Distinctive: line 913
Async/await without error handling: Always use try/catch
- Distinctive: line 914
Promise creation unnecessary: Don't wrap already async functions
- Distinctive: line 915
Mutation of objects: Use spread operator or Object.assign()
- Distinctive: line 917
Blocking event loop: Avoid synchronous operations
- Distinctive: line 919
Not handling promise rejections: Use catch() or try/catch
“Common” is measured: kept by at least 6 in 10 of the 6 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Modern JavaScript Patterns
Comprehensive guide for mastering modern JavaScript (ES6+) features, functional programming patterns, and best practices for writing clean, maintainable, and performant code.
When to Use This Skill
- Refactoring legacy JavaScript to modern syntax
- Implementing functional programming patterns
- Optimizing JavaScript performance
- Writing maintainable and readable code
- Working with asynchronous operations
- Building modern web applications
- Migrating from callbacks to Promises/async-await
- Implementing data transformation pipelines
ES6+ Core Features
1. Arrow Functions
Syntax and Use Cases:
// Traditional function
function add(a, b) {
return a + b;
}
// Arrow function
const add = (a, b) => a + b;
// Single parameter (parentheses optional)
const double = (x) => x * 2;
// No parameters
const getRandom = () => Math.random();
// Multiple statements (need curly 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 {
constructor() {
this.count = 0;
}
// Arrow function preserves 'this' context
increment = () => {
this.count++;
};
// Traditional function loses 'this' in callbacks
incrementTraditional() {
setTimeout(function () {
this.count++; // 'this' is undefined
}, 1000);
}
// Arrow function maintains 'this'
incrementArrow() {
setTimeout(() => {
this.count++; // 'this' refers to Counter instance
}, 1000);
}
}2. Destructuring
Object Destructuring:
const user = {
id: 1,
name: "John Doe",
email: "john@example.com",
address: {
city: "New York",
country: "USA",
},
};
// Basic destructuring
const { name, email } = user;
// Rename variables
const { name: userName, email: userEmail } = user;
// Default values
const { age = 25 } = user;
// Nested destructuring
const {
address: { city, country },
} = user;
// Rest operator
const { id, ...userWithoutId } = user;
// Function parameters
function greet({ name, age = 18 }) {
console.log(`Hello ${name}, you are ${age}`);
}
greet(user);Array Destructuring:
const numbers = [1, 2, 3, 4, 5];
// Basic destructuring
const [first, second] = numbers;
// Skip elements
const [, , third] = numbers;
// Rest operator
const [head, ...tail] = numbers;
// Swapping variables
let a = 1,
b = 2;
[a, b] = [b, a];
// Function return values
function getCoordinates() {
return [10, 20];
}
const [x, y] = getCoordinates();
// Default values
const [one, two, three = 0] = [1, 2];3. Spread and Rest Operators
Spread Operator:
// Array spreading
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];
// Object spreading
const defaults = { theme: "dark", lang: "en" };
const userPrefs = { theme: "light" };
const settings = { ...defaults, ...userPrefs };
// Function arguments
const numbers = [1, 2, 3];
Math.max(...numbers);
// Copying arrays/objects (shallow copy)
const copy = [...arr1];
const objCopy = { ...user };
// Adding items immutably
const newArr = [...arr1, 4, 5];
const newObj = { ...user, age: 30 };Rest Parameters:
// Collect function arguments
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3, 4, 5);
// With regular parameters
function greet(greeting, ...names) {
return `${greeting} ${names.join(", ")}`;
}
greet("Hello", "John", "Jane", "Bob");
// Object rest
const { id, ...userData } = user;
// Array rest
const [first, ...rest] = [1, 2, 3, 4, 5];4. Template Literals
// Basic usage
const name = "John";
const greeting = `Hello, ${name}!`;
// Multi-line strings
const html = `
<div>
<h1>${title}</h1>
<p>${content}</p>
</div>
`;
// Expression evaluation
const price = 19.99;
const total = `Total: $${(price * 1.2).toFixed(2)}`;
// Tagged template literals
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
const value = values[i] || "";
return result + str + `<mark>${value}</mark>`;
}, "");
}
const name = "John";
const age = 30;
const html = highlight`Name: ${name}, Age: ${age}`;
// Output: "Name: <mark>John</mark>, Age: <mark>30</mark>"5. Enhanced Object Literals
const name = "John";
const age = 30;
// Shorthand property names
const user = { name, age };
// Shorthand method names
const calculator = {
add(a, b) {
return a + b;
},
subtract(a, b) {
return a - b;
},
};
// Computed property names
const field = "email";
const user = {
name: "John",
[field]: "john@example.com",
[`get${field.charAt(0).toUpperCase()}${field.slice(1)}`]() {
return this[field];
},
};
// Dynamic property creation
const createUser = (name, ...props) => {
return props.reduce(
(user, [key, value]) => ({
...user,
[key]: value,
}),
{ name },
);
};
const user = createUser("John", ["age", 30], ["email", "john@example.com"]);Asynchronous Patterns
1. Promises
Creating and Using Promises:
// Creating a promise
const fetchUser = (id) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) {
resolve({ id, name: "John" });
} else {
reject(new Error("Invalid ID"));
}
}, 1000);
});
};
// Using promises
fetchUser(1)
.then((user) => console.log(user))
.catch((error) => console.error(error))
.finally(() => console.log("Done"));
// Chaining promises
fetchUser(1)
.then((user) => fetchUserPosts(user.id))
.then((posts) => processPosts(posts))
.then((result) => console.log(result))
.catch((error) => console.error(error));Promise Combinators:
// Promise.all - Wait for all promises
const promises = [fetchUser(1), fetchUser(2), fetchUser(3)];
Promise.all(promises)
.then((users) => console.log(users))
.catch((error) => console.error("At least one failed:", error));
// Promise.allSettled - Wait for all, regardless of outcome
Promise.allSettled(promises).then((results) => {
results.forEach((result) => {
if (result.status === "fulfilled") {
console.log("Success:", result.value);
} else {
console.log("Error:", result.reason);
}
});
});
// Promise.race - First to complete
Promise.race(promises)
.then((winner) => console.log("First:", winner))
.catch((error) => console.error(error));
// Promise.any - First to succeed
Promise.any(promises)
.then((first) => console.log("First success:", first))
.catch((error) => console.error("All failed:", error));2. Async/Await
Basic Usage:
// Async function always returns a Promise
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
const user = await response.json();
return user;
}
// Error handling with try/catch
async function getUserData(id) {
try {
const user = await fetchUser(id);
const posts = await fetchUserPosts(user.id);
return { user, posts };
} catch (error) {
console.error("Error fetching data:", error);
throw error;
}
}
// Sequential vs Parallel execution
async function sequential() {
const user1 = await fetchUser(1); // Wait
const user2 = await fetchUser(2); // Then wait
return [user1, user2];
}
async function parallel() {
const [user1, user2] = await Promise.all([fetchUser(1), fetchUser(2)]);
return [user1, user2];
}Advanced Patterns:
// Async IIFE
(async () => {
const result = await someAsyncOperation();
console.log(result);
})();
// Async iteration
async function processUsers(userIds) {
for (const id of userIds) {
const user = await fetchUser(id);
await processUser(user);
}
}
// Top-level await (ES2022)
const config = await fetch("/config.json").then((r) => r.json());
// Retry logic
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
return await fetch(url);
} catch (error) {
if (i === retries - 1) throw error;
await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
}
}
}
// Timeout wrapper
async function withTimeout(promise, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timeout")), ms),
);
return Promise.race([promise, timeout]);
}Functional Programming Patterns
1. Array Methods
Map, Filter, Reduce:
const users = [
{ id: 1, name: "John", age: 30, active: true },
{ id: 2, name: "Jane", age: 25, active: false },
{ id: 3, name: "Bob", age: 35, active: true },
];
// Map - Transform array
const names = users.map((user) => user.name);
const upperNames = users.map((user) => user.name.toUpperCase());
// Filter - Select elements
const activeUsers = users.filter((user) => user.active);
const adults = users.filter((user) => user.age >= 18);
// Reduce - Aggregate data
const totalAge = users.reduce((sum, user) => sum + user.age, 0);
const avgAge = totalAge / users.length;
// Group by property
const byActive = users.reduce((groups, user) => {
const key = user.active ? "active" : "inactive";
return {
...groups,
[key]: [...(groups[key] || []), user],
};
}, {});
// Chaining methods
const result = users
.filter((user) => user.active)
.map((user) => user.name)
.sort()
.join(", ");Advanced Array Methods:
// Find - First matching element
const user = users.find((u) => u.id === 2);
// FindIndex - Index of first match
const index = users.findIndex((u) => u.name === "Jane");
// Some - At least one matches
const hasActive = users.some((u) => u.active);
// Every - All match
const allAdults = users.every((u) => u.age >= 18);
// FlatMap - Map and flatten
const userTags = [
{ name: "John", tags: ["admin", "user"] },
{ name: "Jane", tags: ["user"] },
];
const allTags = userTags.flatMap((u) => u.tags);
// From - Create array from iterable
const str = "hello";
const chars = Array.from(str);
const numbers = Array.from({ length: 5 }, (_, i) => i + 1);
// Of - Create array from arguments
const arr = Array.of(1, 2, 3);2. Higher-Order Functions
Functions as Arguments:
// Custom forEach
function forEach(array, callback) {
for (let i = 0; i < array.length; i++) {
callback(array[i], i, array);
}
}
// Custom map
function map(array, transform) {
const result = [];
for (const item of array) {
result.push(transform(item));
}
return result;
}
// Custom filter
function filter(array, predicate) {
const result = [];
for (const item of array) {
if (predicate(item)) {
result.push(item);
}
}
return result;
}Functions Returning Functions:
// Currying
const multiply = (a) => (b) => a * b;
const double = multiply(2);
const triple = multiply(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
// Partial application
function partial(fn, ...args) {
return (...moreArgs) => fn(...args, ...moreArgs);
}
const add = (a, b, c) => a + b + c;
const add5 = partial(add, 5);
console.log(add5(3, 2)); // 10
// Memoization
function memoize(fn) {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
};
}
const fibonacci = memoize((n) => {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
});3. Composition and Piping
// Function composition
const compose =
(...fns) =>
(x) =>
fns.reduceRight((acc, fn) => fn(acc), x);
const pipe =
(...fns) =>
(x) =>
fns.reduce((acc, fn) => fn(acc), x);
// Example usage
const addOne = (x) => x + 1;
const double = (x) => x * 2;
const square = (x) => x * x;
const composed = compose(square, double, addOne);
console.log(composed(3)); // ((3 + 1) * 2)^2 = 64
const piped = pipe(addOne, double, square);
console.log(piped(3)); // ((3 + 1) * 2)^2 = 64
// Practical example
const processUser = pipe(
(user) => ({ ...user, name: user.name.trim() }),
(user) => ({ ...user, email: user.email.toLowerCase() }),
(user) => ({ ...user, age: parseInt(user.age) }),
);
const user = processUser({
name: " John ",
email: "JOHN@EXAMPLE.COM",
age: "30",
});4. Pure Functions and Immutability
// Impure function (modifies input)
function addItemImpure(cart, item) {
cart.items.push(item);
cart.total += item.price;
return cart;
}
// Pure function (no side effects)
function addItemPure(cart, item) {
return {
...cart,
items: [...cart.items, item],
total: cart.total + item.price,
};
}
// Immutable array operations
const numbers = [1, 2, 3, 4, 5];
// Add to array
const withSix = [...numbers, 6];
// Remove from array
const withoutThree = numbers.filter((n) => n !== 3);
// Update array element
const doubled = numbers.map((n) => (n === 3 ? n * 2 : n));
// Immutable object operations
const user = { name: "John", age: 30 };
// Update property
const olderUser = { ...user, age: 31 };
// Add property
const withEmail = { ...user, email: "john@example.com" };
// Remove property
const { age, ...withoutAge } = user;
// Deep cloning (simple approach)
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
// Better deep cloning
const structuredClone = (obj) => globalThis.structuredClone(obj);Modern Class Features
// Class syntax
class User {
// Private fields
#password;
// Public fields
id;
name;
// Static field
static count = 0;
constructor(id, name, password) {
this.id = id;
this.name = name;
this.#password = password;
User.count++;
}
// Public method
greet() {
return `Hello, ${this.name}`;
}
// Private method
#hashPassword(password) {
return `hashed_${password}`;
}
// Getter
get displayName() {
return this.name.toUpperCase();
}
// Setter
set password(newPassword) {
this.#password = this.#hashPassword(newPassword);
}
// Static method
static create(id, name, password) {
return new User(id, name, password);
}
}
// Inheritance
class Admin extends User {
constructor(id, name, password, role) {
super(id, name, password);
this.role = role;
}
greet() {
return `${super.greet()}, I'm an admin`;
}
}Modules (ES6)
// Exporting
// math.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export class Calculator {
// ...
}
// Default export
export default function multiply(a, b) {
return a * b;
}
// Importing
// app.js
import multiply, { PI, add, Calculator } from "./math.js";
// Rename imports
import { add as sum } from "./math.js";
// Import all
import * as Math from "./math.js";
// Dynamic imports
const module = await import("./math.js");
const { add } = await import("./math.js");
// Conditional loading
if (condition) {
const module = await import("./feature.js");
module.init();
}Iterators and Generators
// Custom iterator
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
return {
current: this.from,
last: this.to,
next() {
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
},
};
},
};
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
// Generator function
function* rangeGenerator(from, to) {
for (let i = from; i <= to; i++) {
yield i;
}
}
for (const num of rangeGenerator(1, 5)) {
console.log(num);
}
// Infinite generator
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
// Async generator
async function* fetchPages(url) {
let page = 1;
while (true) {
const response = await fetch(`${url}?page=${page}`);
const data = await response.json();
if (data.length === 0) break;
yield data;
page++;
}
}
for await (const page of fetchPages("/api/users")) {
console.log(page);
}Modern Operators
// Optional chaining
const user = { name: "John", address: { city: "NYC" } };
const city = user?.address?.city;
const zipCode = user?.address?.zipCode; // undefined
// Function call
const result = obj.method?.();
// Array access
const first = arr?.[0];
// Nullish coalescing
const value = null ?? "default"; // 'default'
const value = undefined ?? "default"; // 'default'
const value = 0 ?? "default"; // 0 (not 'default')
const value = "" ?? "default"; // '' (not 'default')
// Logical assignment
let a = null;
a ??= "default"; // a = 'default'
let b = 5;
b ??= 10; // b = 5 (unchanged)
let obj = { count: 0 };
obj.count ||= 1; // obj.count = 1
obj.count &&= 2; // obj.count = 2Performance Optimization
// Debounce
function debounce(fn, delay) {
let timeoutId;
return (...args) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
}
const searchDebounced = debounce(search, 300);
// Throttle
function throttle(fn, limit) {
let inThrottle;
return (...args) => {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
const scrollThrottled = throttle(handleScroll, 100);
// Lazy evaluation
function* lazyMap(iterable, transform) {
for (const item of iterable) {
yield transform(item);
}
}
// Use only what you need
const numbers = [1, 2, 3, 4, 5];
const doubled = lazyMap(numbers, (x) => x * 2);
const first = doubled.next().value; // Only computes first valueBest Practices
- Use const by default: Only use let when reassignment is needed
- Prefer arrow functions: Especially for callbacks
- Use template literals: Instead of string concatenation
- Destructure objects and arrays: For cleaner code
- Use async/await: Instead of Promise chains
- Avoid mutating data: Use spread operator and array methods
- Use optional chaining: Prevent "Cannot read property of undefined"
- Use nullish coalescing: For default values
- Prefer array methods: Over traditional loops
- Use modules: For better code organization
- Write pure functions: Easier to test and reason about
- Use meaningful variable names: Self-documenting code
- Keep functions small: Single responsibility principle
- Handle errors properly: Use try/catch with async/await
- Use strict mode:
'use strict'for better error catching
Common Pitfalls
- this binding confusion: Use arrow functions or bind()
- Async/await without error handling: Always use try/catch
- Promise creation unnecessary: Don't wrap already async functions
- Mutation of objects: Use spread operator or Object.assign()
- Forgetting await: Async functions return promises
- Blocking event loop: Avoid synchronous operations
- Memory leaks: Clean up event listeners and timers
- Not handling promise rejections: Use catch() or try/catch
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

