patterns

JavaScript design patterns and architectural best practices.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "patterns" with this command: npx skills add pluginagentmarketplace/custom-plugin-javascript/pluginagentmarketplace-custom-plugin-javascript-patterns

JavaScript Patterns Skill

Quick Reference Card

Creational Patterns

Factory

function createUser(type) {
  const users = {
    admin: () => ({ role: 'admin', permissions: ['all'] }),
    user: () => ({ role: 'user', permissions: ['read'] })
  };
  return users[type]?.() ?? users.user();
}

Singleton

class Database {
  static #instance;

  static getInstance() {
    if (!Database.#instance) {
      Database.#instance = new Database();
    }
    return Database.#instance;
  }
}

Builder

class QueryBuilder {
  #query = { select: '*', from: '', where: [] };

  select(fields) { this.#query.select = fields; return this; }
  from(table) { this.#query.from = table; return this; }
  where(condition) { this.#query.where.push(condition); return this; }
  build() { return this.#query; }
}

new QueryBuilder()
  .select('name, email')
  .from('users')
  .where('active = true')
  .build();

Structural Patterns

Module

const Counter = (function() {
  let count = 0; // Private

  return {
    increment: () => ++count,
    decrement: () => --count,
    get: () => count
  };
})();

Facade

class ApiClient {
  async getUser(id) {
    const response = await fetch(`/api/users/${id}`);
    if (!response.ok) throw new Error('Failed');
    return response.json();
  }

  async updateUser(id, data) {
    return this.#request('PUT', `/api/users/${id}`, data);
  }

  #request(method, url, data) {
    return fetch(url, {
      method,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    }).then(r => r.json());
  }
}

Decorator

function withLogging(fn) {
  return function(...args) {
    console.log('Calling:', fn.name, args);
    const result = fn.apply(this, args);
    console.log('Result:', result);
    return result;
  };
}

const add = withLogging((a, b) => a + b);

Behavioral Patterns

Observer (Pub/Sub)

class EventEmitter {
  #events = new Map();

  on(event, handler) {
    if (!this.#events.has(event)) this.#events.set(event, []);
    this.#events.get(event).push(handler);
    return () => this.off(event, handler);
  }

  off(event, handler) {
    const handlers = this.#events.get(event) ?? [];
    this.#events.set(event, handlers.filter(h => h !== handler));
  }

  emit(event, data) {
    (this.#events.get(event) ?? []).forEach(h => h(data));
  }
}

Strategy

const validators = {
  email: (v) => /\S+@\S+/.test(v),
  phone: (v) => /^\d{10}$/.test(v),
  required: (v) => v?.trim().length > 0
};

function validate(value, rules) {
  return rules.every(rule => validators[rule]?.(value) ?? true);
}

validate('test@test.com', ['required', 'email']); // true

Command

class CommandManager {
  #history = [];
  #index = -1;

  execute(command) {
    command.execute();
    this.#history = this.#history.slice(0, this.#index + 1);
    this.#history.push(command);
    this.#index++;
  }

  undo() {
    if (this.#index >= 0) {
      this.#history[this.#index--].undo();
    }
  }

  redo() {
    if (this.#index < this.#history.length - 1) {
      this.#history[++this.#index].execute();
    }
  }
}

Modern Patterns

Composition

const withLogger = (obj) => ({
  ...obj,
  log: (msg) => console.log(`[${obj.name}] ${msg}`)
});

const withValidator = (obj) => ({
  ...obj,
  validate: () => !!obj.value
});

const field = withValidator(withLogger({ name: 'email', value: '' }));

Middleware

function createPipeline(...middlewares) {
  return (input) => middlewares.reduce(
    (acc, fn) => fn(acc),
    input
  );
}

const process = createPipeline(
  (x) => x.trim(),
  (x) => x.toLowerCase(),
  (x) => x.replace(/\s+/g, '-')
);

process('  Hello World  '); // 'hello-world'

Troubleshooting

When to Use

PatternUse When
FactoryMultiple similar objects
SingletonSingle shared instance
ObserverEvent-driven communication
StrategySwappable algorithms
FacadeComplex subsystem

Anti-Patterns to Avoid

  • God objects (do everything)
  • Tight coupling
  • Callback hell
  • Magic numbers/strings
  • Premature optimization

Related

  • Agent 06: Modern ES6+ (detailed learning)
  • Skill: functions: Function patterns
  • Skill: modern-javascript: Classes

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

performance

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

data-structures

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

asynchronous

No summary provided by upstream source.

Repository SourceNeeds Review