JavaScript
Modern JS/TS patterns for ES2020+ with async code, safe property access, modern syntax.
When to Use
Use when:
- Writing JavaScript with ES2020+ features
- Refactoring legacy JS to modern syntax
- Implementing async operations (promises, async/await)
- Using destructuring, optional chaining, nullish coalescing
Don't use for TypeScript (typescript skill), React (react skill), or Node.js backend.
Critical Patterns
✅ REQUIRED: ES Module Imports
// CORRECT: Named imports (explicit, tree-shakeable)
import { readFileSync, existsSync } from "fs";
import { join, resolve } from "path";
// CORRECT: Default import for modules with single export
import express from "express";
// WRONG: require() in ES modules
const fs = require("fs");
// WRONG: Dynamic import when static works
async function doWork() {
const fs = await import("fs"); // unnecessary
}
✅ REQUIRED: No Dead Code
// WRONG: Unused variables and imports
import { something } from "./lib"; // never used
const unused = 42;
function neverCalled() {}
// CORRECT: Every import, variable, and function is used
import { needed } from "./lib";
const count = needed();
✅ REQUIRED: const/let, Never var
// CORRECT
const API_URL = "https://api.example.com";
let count = 0;
// WRONG: var (function-scoped, hoisting issues)
var count = 0;
✅ REQUIRED: async/await for Async Operations
// CORRECT
async function fetchData() {
try {
const response = await fetch(url);
return await response.json();
} catch (error) {
console.error(error);
}
}
// WRONG: promise chains
function fetchData() {
return fetch(url)
.then((res) => res.json())
.catch((error) => console.error(error));
}
✅ REQUIRED: Optional Chaining and Nullish Coalescing
// CORRECT: safe access + nullish coalescing
const name = user?.profile?.name ?? "Anonymous";
const result = obj?.method?.();
const port = config.port ?? 3000; // 0 won't fallback
// WRONG: || treats 0, '', false as falsy
const port = config.port || 3000; // 0 fallbacks to 3000!
// WRONG: verbose manual checks
const name = (user && user.profile && user.profile.name) || "Anonymous";
✅ REQUIRED: Explicit Boolean Coercion
// CORRECT
const hasData = !!data;
const isValid = Boolean(value);
// WRONG: implicit coercion hides intent
if (data) { /* unclear: existence or truthiness? */ }
✅ REQUIRED: Promise.all for Parallel Operations
// CORRECT: parallel
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments(),
]);
// WRONG: sequential (3x slower)
const users = await fetchUsers();
const posts = await fetchPosts();
const comments = await fetchComments();
Decision Tree
Importing a module?
→ Named imports: import { x } from 'mod' — never require() in ES modules
Unused import/variable?
→ Delete it — no dead code
Async operation?
→ async/await with try/catch
String concatenation?
→ Template literals: Hello ${name}
Default value?
→ ?? for null/undefined; || for any falsy
Property might not exist?
→ Optional chaining: obj?.prop?.nested
Iterate array?
→ .map(), .filter(), .reduce() — use for...of for early breaks
Copy object/array?
→ Spread: {...obj}, [...arr]
Callback?
→ Arrow function unless this context is needed
Multiple independent awaits?
→ Promise.all() for parallel execution
Example
const fetchData = async (url) => {
try {
const response = await fetch(url);
const data = await response.json();
return data?.results ?? [];
} catch (error) {
console.error("Fetch failed:", error);
return [];
}
};
const { name, age = 18 } = user;
const greeting = `Hello, ${name}!`;
Edge Cases
- Parallel async:
Promise.all()for concurrent execution - Array holes:
.filter(Boolean)to clean sparse arrays - Number precision: Use decimal.js for financial calculations
- Equality: Always
===(never==) - this binding: Arrow functions don't bind
this
Checklist
- ES module imports (
import/export), norequire() - Named imports over namespace imports
- No unused imports, variables, or functions
-
const/letonly (novar) -
async/awaitwith try/catch for async code -
?.and??for safe access and defaults -
Promise.all()for independent parallel fetches -
===for all equality checks - Template literals for string interpolation
- Destructuring for objects and arrays
- Arrow functions for callbacks
- Modern array methods (
.map,.filter,.reduce)