# Javascript

> Reglas de JavaScript vanilla ES6+ - programación defensiva, módulos, DOM, fetch

- **Type:** Skill
- **Install:** `agentstack add skill-14bryanespinoza-agent-stack-javascript`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [14BryanEspinoza](https://agentstack.voostack.com/s/14bryanespinoza)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [14BryanEspinoza](https://github.com/14BryanEspinoza)
- **Source:** https://github.com/14BryanEspinoza/agent-stack/tree/agent-stack/skills/javascript

## Install

```sh
agentstack add skill-14bryanespinoza-agent-stack-javascript
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# JavaScript Vanilla ES6+ - Reglas

JavaScript vanilla ES6+ es el enfoque preferido.

## 1. Instalación y Versión

### Versión mínima

| Tecnología | Versión Mínima    |
| ---------- | ----------------- |
| JavaScript | ES2020+ (moderno) |
| Node.js    | 18+               |

---

## 2. Cuándo USAR JavaScript

| Caso                        | Justificación                            |
| --------------------------- | ---------------------------------------- |
| **Interactividad dinámica** | Modales, acordeones, tabs                |
| **Manipulación del DOM**    | Crear/actualizar contenido dinámicamente |
| **Fetch/AJAX**              | Obtener/enviar datos sin recargar        |
| **Validación cliente**      | Validación en tiempo real                |
| **APIs del navegador**      | LocalStorage, Geolocation, etc.          |

---

## 3. Cuándo NO USAR JavaScript

| En lugar de...      | Usar...                    |
| ------------------- | -------------------------- |
| Animaciones simples | CSS Transitions/Animations |
| Tooltips simples    | CSS-only o title attribute |
| Modales simples     | HTML ``            |
| Acordeones simples  | HTML `/` |
| Carousels simples   | CSS scroll snap            |
| Dropdowns simples   | HTML ``            |

---

## 4. APIs Preferidas

| En lugar de...                | Usar...                                    |
| ----------------------------- | ------------------------------------------ |
| `var`                         | `const` (por defecto), `let` (si reasigna) |
| `function`                    | Arrow functions cuando corresponda         |
| Callbacks                     | `async/await` + `Promise`                  |
| `$.ajax`                      | `fetch`                                    |
| `for` loops                   | `forEach`, `map`, `filter`, `reduce`       |
| Strings concat                | Template literals `` `hello ${name}` ``    |
| `setTimeout` para animaciones | CSS transitions                            |
| Animaciones con JS            | Web Animations API                         |
| Detectar elementos en vista   | IntersectionObserver                       |

---

## 5. Selección DOM

```javascript
// Selección simple
const element = document.querySelector(".class");
const elements = document.querySelectorAll(".class");

// Por ID (más rápido)
const el = document.getElementById("my-id");

// Con dataset
element.dataset.property = "value";
const value = element.dataset.property;
```

---

## 6. Manipulación del DOM

### Crear elementos

```javascript
// Crear elemento
const div = document.createElement("div");
div.className = "card";
div.textContent = "Contenido";

// Crear con innerHTML (solo si no hay datos de usuario)
container.innerHTML = 'Contenido seguro';

// Evitar XSS con textContent
const userInput = 'alert("xss")';
element.textContent = userInput; // Seguro
element.innerHTML = userInput; // Peligroso
```

### Agregar elementos

```javascript
// Append (al final)
parent.appendChild(element);
parent.append("Texto", element);

// Prepend (al inicio)
parent.prepend(element);

// Before/After
sibling.before(element);
sibling.after(element);

// Reemplazar
oldElement.replaceWith(newElement);

// Remover
element.remove();
element.parentNode.removeChild(element);
```

### Templates

```javascript
// Usar template para estructuras complejas
const template = document.querySelector("#card-template");
const card = template.content.cloneNode(true);
card.querySelector(".title").textContent = "Nuevo título";
document.querySelector(".container").appendChild(card);
```

---

## 7. Eventos

### Event listener

```javascript
// Basic
element.addEventListener("click", (event) => {
  console.log(event.target);
});

// Con opciones
element.addEventListener("click", handler, { once: true, passive: true });

// Remover listener
element.removeEventListener("click", handler);
```

### Evitar onclick en HTML

```html

Guardar
Acción

Guardar
Acción

  document.querySelectorAll("[data-action]").forEach((el) => {
    el.addEventListener("click", (e) => {
      e.preventDefault();
      // acción...
    });
  });

```

### Eventos de teclado

```javascript
// Keyboard accessible
element.addEventListener("keydown", (event) => {
  if (event.key === "Enter" || event.key === " ") {
    event.preventDefault();
    // acción...
  }
});
```

---

## 8. Módulos ES (ESM)

### Estructura de archivos

```text
src/
├── js/
│   ├── main.js        # Entry point
│   ├── editor.js      # Lógica del editor
│   └── utils.js       # Funciones helper
```

### Export/Import

```javascript
// editor.js
export function initEditor() {
  // ...
}

export const EDITOR_CONFIG = {
  maxLength: 10000,
};

// main.js
import { initEditor } from "./editor.js";

document.addEventListener("DOMContentLoaded", () => {
  initEditor();
});
```

### Configuración en HTML

```html

```

---

## 9. Fetch API

### Solicitud básica

```javascript
async function fetchData(url) {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Fetch failed:", error);
    return null;
  }
}
```

### Con headers

```javascript
async function postData(url, data) {
  const response = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Bearer token123",
    },
    body: JSON.stringify(data),
  });
  return response.json();
}
```

### Abort controller (cancelar petición)

```javascript
const controller = new AbortController();
const signal = controller.signal;

fetch(url, { signal })
  .then((response) => response.json())
  .catch((error) => {
    if (error.name === "AbortError") {
      console.log("Request cancelled");
    }
  });

// Cancelar después de 5 segundos
setTimeout(() => controller.abort(), 5000);
```

### Retry automático

```javascript
async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i  setTimeout(r, 1000 * (i + 1)));
    }
  }
}
```

---

## 10. Programación Defensiva

### Validar inputs

```javascript
function processData(data) {
  if (!data || typeof data !== "object") {
    console.error("Invalid data");
    return null;
  }
  // procesar...
}
```

### Optional chaining y nullish

```javascript
// Optional chaining
const value = obj?.nested?.property;
const arr = data?.items?.[0];
const method = obj?.doSomething?.();

// Nullish coalescing
const name = user.name ?? "Anonymous";
const count = items.length ?? 0;
```

### Validar elementos

```javascript
// Verificar que elemento existe antes de usar
const button = document.querySelector(".btn-submit");
if (button) {
  button.addEventListener("click", handleSubmit);
}
```

---

## 11. Storage

### localStorage

```javascript
// Guardar
localStorage.setItem("user", JSON.stringify({ name: "John" }));

// Leer
const user = JSON.parse(localStorage.getItem("user") || "{}");

// Remover
localStorage.removeItem("user");

// Verificar disponibilidad
const hasStorage = () => {
  try {
    localStorage.setItem("test", "test");
    localStorage.removeItem("test");
    return true;
  } catch (e) {
    return false;
  }
};
```

### sessionStorage

```javascript
// Similar a localStorage pero se limpia al cerrar pestaña
sessionStorage.setItem("tempData", "value");
const temp = sessionStorage.getItem("tempData");
```

---

## 12. Date/Time (Intl API)

### Formatear fechas

```javascript
const date = new Date();

// Formato local
new Intl.DateTimeFormat("es-ES", {
  year: "numeric",
  month: "long",
  day: "numeric",
}).format(date);

// Formato corto
new Intl.DateTimeFormat("en-US", {
  month: "short",
  day: "numeric",
}).format(date);
```

### Formatear números

```javascript
// Moneda
new Intl.NumberFormat("es-ES", {
  style: "currency",
  currency: "EUR",
}).format(1234.56);

// Porcentaje
new Intl.NumberFormat("en-US", {
  style: "percent",
}).format(0.75);
```

---

## 13. Intersection Observer

Detectar cuando un elemento entra en el viewport:

```javascript
const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        entry.target.classList.add("visible");
        // O cargar contenido lazy
      }
    });
  },
  {
    root: null,
    rootMargin: "0px",
    threshold: 0.1,
  },
);

observer.observe(document.querySelector(".lazy-load"));
```

---

## 14. Web Animations API

```javascript
element.animate(
  [
    { opacity: 0, transform: "translateY(20px)" },
    { opacity: 1, transform: "translateY(0)" },
  ],
  {
    duration: 300,
    easing: "ease-out",
    fill: "forwards",
  },
);
```

---

## 15. Performance

### Evitar Reflows/Repaints

```javascript
// ❌ Malo - múltiples reflows
element.style.width = "100px";
element.style.height = "100px";
element.style.padding = "10px";

// ✅ Bueno - usar CSS classes o cssText
element.style.cssText = "width: 100px; height: 100px; padding: 10px;";

// ✅ Mejor - usar classList
element.classList.add("active");
```

### Debounce

```javascript
function debounce(fn, delay) {
  let timeoutId;
  return (...args) => {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn(...args), delay);
  };
}

// Uso
const debouncedSearch = debounce(search, 300);
input.addEventListener("input", debouncedSearch);
```

### Throttle

```javascript
function throttle(fn, limit) {
  let inThrottle;
  return (...args) => {
    if (!inThrottle) {
      fn(...args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}

// Uso
const throttledScroll = throttle(handleScroll, 100);
window.addEventListener("scroll", throttledScroll);
```

---

## 16. Prohibiciones

- ❌ **NO usar**: Vue, Svelte, Angular (sin autorización)
- ❌ **NO usar**: React (sin cargar skill `react`)
- ❌ **NO usar**: TypeScript para vanilla (sin cargar skill `typescript`)
- ❌ No usar `var`
- ❌ No dejar `console.log`, `debugger` en código final
- ❌ No usar jQuery para selección básica (usar vanilla)
- ❌ No usar JavaScript para animaciones simples (usar CSS)
- ❌ No usar `onclick` en HTML (usar addEventListener)
- ❌ No usar `innerHTML` con datos de usuario (riesgo XSS)

---

## 17. Referencias

> **Nota:** Para HTML semántico, ver [HTML](../html/SKILL.md)
> **Nota:** Para estilos CSS, ver [CSS](../css/SKILL.md)

---

## 18. Dependencias Comunes

JavaScript vanilla típicamente no requiere dependencias. Para proyectos específicos, considerar:

| Paquete   | Uso                         |
| --------- | --------------------------- |
| date-fns  | Fechas                      |
| lodash-es | Utilidades (tree-shakeable) |

---

Última actualización: 2026-07

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [14BryanEspinoza](https://github.com/14BryanEspinoza)
- **Source:** [14BryanEspinoza/agent-stack](https://github.com/14BryanEspinoza/agent-stack)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-14bryanespinoza-agent-stack-javascript
- Seller: https://agentstack.voostack.com/s/14bryanespinoza
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
