joabgonzalez

javascript

"Modern JavaScript (ES2020+) patterns. Trigger: When writing JavaScript code, using ES2020+ features, or refactoring legacy JS."

joabgonzalez 5 Updated 3mo ago
GitHub

Install

npx skillscat add joabgonzalez/ai-agents-skills/javascript

Install via the SkillsCat registry.

SKILL.md

JavaScript Skill

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), no require()
  • Named imports over namespace imports
  • No unused imports, variables, or functions
  • const/let only (no var)
  • async/await with 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)

Resources