Claude
Skills
Sign in
Back

javascript

Included with Lifetime
$97 forever

Core JavaScript language conventions, idioms, and modern practices. Invoke whenever task involves any interaction with JavaScript code — writing, reviewing, refactoring, debugging, or understanding .js/.jsx files and JavaScript projects.

Productivity

What this skill does


# JavaScript

**Clarity is the highest JavaScript virtue. If your code requires a comment to explain its control flow, rewrite it.**

JavaScript rewards explicit, readable code. Prefer boring patterns that are easy to understand over clever tricks that
save characters.

## References

- **Functions, closures, composition** → [`${CLAUDE_SKILL_DIR}/references/functions.md`] — Arrow function examples,
  closure patterns, early return, parameter destructuring
- **Async patterns, error handling, concurrency** → [`${CLAUDE_SKILL_DIR}/references/async.md`] — Promise.all/race/any
  examples, cancellation, custom error classes, for-await
- **Objects, arrays, iteration, Map/Set** → [`${CLAUDE_SKILL_DIR}/references/objects-and-arrays.md`] — Iteration
  decision table, destructuring patterns, immutable updates, generators
- **ES modules, imports, barrel files** → [`${CLAUDE_SKILL_DIR}/references/modules.md`] — Import ordering, barrel file
  rationale, directory import pitfalls, dynamic imports
- **JSDoc typing, full tag catalog** → [`${CLAUDE_SKILL_DIR}/references/jsdoc.md`] — Full tag reference (@callback,
  @template, @enum), type assertions, class modifiers
- **General JS idioms and edge cases** → [`${CLAUDE_SKILL_DIR}/references/idioms.md`] — Variable/naming examples,
  equality coercion table, modern syntax patterns

## Variables and Declarations

- **`const` by default.** Use `let` only when reassignment is required. Never `var`.
- **`const` prevents reassignment, not mutation.** Objects and arrays declared with `const` can still be mutated.
- **Block scope only.** `let`/`const` are block-scoped; `var` is function-scoped and hoists — this causes bugs in loops
  and conditionals.
- **One declaration per line.** Never chain `const a = 1, b = 2`.
- **Group declarations.** `const` first, then `let`.

## Naming

| Entity                      | Style                            | Examples                            |
| --------------------------- | -------------------------------- | ----------------------------------- |
| Variables, functions        | camelCase                        | `userName`, `fetchData`             |
| Classes, constructors       | PascalCase                       | `UserService`, `HttpClient`         |
| True compile-time constants | SCREAMING_SNAKE_CASE             | `MAX_RETRIES`, `API_BASE_URL`       |
| Private fields/methods      | `#` prefix (class)               | `#count`, `#validate()`             |
| Booleans                    | `is`/`has`/`can`/`should` prefix | `isValid`, `hasAccess`              |
| File names                  | kebab-case or camelCase          | `user-service.js`, `userService.js` |

- **SCREAMING_SNAKE_CASE is for true constants only** — values known at compile time, never computed at runtime. A
  variable holding a function return value uses camelCase.
- **Descriptive names.** `userCount` not `n`. Short names (`i`, `x`) only in tiny scopes (loop indices, simple arrow
  callbacks).
- **Accepted abbreviations:** `url`, `id`, `err`, `ctx`, `req`, `res` — universally understood. Avoid all others.
- **No redundant context.** `car.make` not `car.carMake`.
- **Consistent vocabulary.** Use the same word for the same concept throughout a codebase — `getUser()` everywhere, not
  `getUserInfo()` / `getClientData()` / `getCustomerRecord()`.

## Equality and Safety

- **Always `===` and `!==`.** Never `==` except for `value == null` (checks both `null` and `undefined`).
- **`??` over `||`** for defaults — `||` treats `0`, `""`, `false` as falsy.
- **`?.` for optional access.** Don't overuse — missing data you expect should throw, not silently return `undefined`.
- **Know the falsy values:** `false`, `0`, `-0`, `0n`, `""`, `null`, `undefined`, `NaN`. Everything else is truthy,
  including `[]`, `{}`, and `"0"`.

## Ternary Operator

- **One-liners or split-per-branch only.** Ternaries are acceptable in two forms:

  ```js
  // OK — fits on one line
  const label = isActive ? 'Active' : 'Inactive';

  // OK — each branch on its own line
  const label = isActive
    ? buildActiveLabel(user)
    : buildInactiveLabel(user);
  ```

  Any ternary that doesn't fit one of these two patterns must be rewritten as `if`/`else` or early return.

- **Nested ternaries are banned.** No exceptions. Use `if`/`else`, early returns, or a lookup object.

## Modern Syntax

- **Template literals** for string interpolation: `` `Hello, ${name}` ``. Don't use template literals for strings
  without interpolation — use plain quotes.
- **Spread for copies:** `{ ...obj }` and `[...arr]`. Never `Object.assign`.
- **Rest parameters** to collect remaining: `const { id, ...rest } = user`.
- **Shorthand properties:** `{ name, age }` not `{ name: name, age: age }`. Group shorthand properties at the top of
  object literals.
- **Computed property names:** `{ [key]: value, [`${key}Date`]: new Date() }`.
- **Logical assignment operators:** `opts.timeout ??= 5000` (assign if nullish), `opts.name ||= "default"` (assign if
  falsy), `opts.handler &&= wrap(opts.handler)` (assign if truthy).

## Functions

- **Arrow functions** for callbacks and anonymous functions. Use function declarations only when hoisting or `this`
  binding is needed.
- **Prefer parentheses** around arrow function parameters even for single params — smaller diffs when adding/removing
  parameters.
- **Implicit return** for single expressions (no braces). Explicit return (braces) for multi-statement bodies.
- **Arrow functions capture lexical `this`** — they do NOT have their own `this`. Never use arrow functions as object
  methods or on prototypes.
- **Destructured options** for 3+ parameters. Self-documenting and order-independent.
- **Default parameters** over `||` or manual checks. Defaults are evaluated left-to-right and can reference earlier
  params.
- **Rest parameters** over `arguments` object. `arguments` is array-like, not a real Array.
- **Early return.** Guard clauses first, happy path flat. Reduce nesting.
- **One function, one job.** If the name contains "and", split it.
- **Keep functions under ~30 lines.** Extract helpers. Use composition over complex branching.
- **Prefer pure functions** (same input = same output, no side effects). Isolate side effects (DOM, network, logging) —
  don't hide them inside data transformations.
- **Closures retain references to outer variables, not copies.** Be cautious with large objects captured unintentionally
  — they won't be garbage collected until the closure is released.

## Async

- **`async`/`await` over `.then()` chains** for sequential operations.
- **Always `await` promises.** Missing `await` = floating promise = silent failures.
- **`return await` only inside `try` blocks** where you need to catch the awaited error. Otherwise just `return promise`
  — no need for `async` wrapper.
- **`Promise.all`** for independent parallel work. Rejects on first rejection.
- **`Promise.allSettled`** when all results matter regardless of individual failures.
- **`Promise.race`** for timeouts. **`Promise.any`** for fallbacks (rejects only when ALL reject).
- **Avoid sequential awaits in loops.** Use `Promise.all(items.map(...))` for parallel. Use a concurrency limiter (e.g.
  `p-map`) for large arrays.
- **Throw `Error` objects**, never strings or plain objects — strings lose stack traces.
- **Custom error classes** when callers need to distinguish errors: extend `Error`, set `this.name`, add context
  properties.
- **Never swallow errors.** Every `catch` must handle, rethrow, or report. Empty `catch` blocks hide bugs.
  `console.log(err)` alone is not handling.
- **Let errors propagate** to a top-level handler when possible. Don't wrap every `await` in `try`/`catch` — only where
  you need to handle at that level.
- **Attach `.catch()` to non-awaited promise chains.** Unhandled rejections crash Node.js. Fire-and-forget:
  `fetchData().catch(reportError)`.
- **Only use `new Promise()`** to wrap callback-based APIs. Most async code should comp

Related in Productivity