📝 Javascript
← Volver

JavaScript: Guía Completa

Índice

  1. ¿Qué es JavaScript?
  2. Sintaxis fundamental
  3. Paradigmas de programación
  4. Programación asíncrona y Promesas
  5. Manipulación de Strings: split() y join()
  6. Ecosistema: Node.js
  7. Gestión de paquetes: npm, pnpm y yarn
  8. Frameworks y librerías principales
  9. Herramientas de construcción (Build Tools)
  10. Resumen general

1. ¿Qué es JavaScript?

JavaScript (abreviado JS) es un lenguaje de programación interpretado, de alto nivel y tipado dinámico. Nació en 1995 para añadir interactividad a las páginas web, pero hoy se usa tanto en el frontend (navegador) como en el backend (servidor con Node.js), en aplicaciones móviles, scripts de automatización y mucho más.

Características clave:


2. Sintaxis fundamental

Variables

var   nombre = "Ana";   // Ámbito de función (evitar en código moderno)
let   edad   = 25;      // Ámbito de bloque, reasignable
const PI     = 3.1416;  // Ámbito de bloque, NO reasignable

Regla general: usa const por defecto; let solo cuando necesites reasignar. Evita var.


Tipos de datos

// Primitivos
let texto    = "Hola mundo";       // String
let numero   = 42;                 // Number
let decimal  = 3.14;               // Number (no hay tipo Float separado)
let activo   = true;               // Boolean
let nulo     = null;               // Null (ausencia intencional de valor)
let indefinido;                    // undefined (variable declarada sin valor)
let id       = Symbol("id");       // Symbol (identificador único)
let grande   = 9007199254740993n;  // BigInt

// Compuestos
let array    = [1, 2, 3];
let objeto   = { nombre: "Ana", edad: 25 };
let funcion  = function() {};

Operadores

// Aritméticos
5 + 3   // 8
10 - 4  // 6
3 * 7   // 21
9 / 2   // 4.5
9 % 2   // 1  (módulo / resto)
2 ** 3  // 8  (potencia)

// Comparación — SIEMPRE usa === y !== (compara valor Y tipo)
5 === "5"  // false  ✅ recomendado
5 ==  "5"  // true   ❌ hace coerción de tipos

// Lógicos
true && false  // false  (AND)
true || false  // true   (OR)
!true          // false  (NOT)

// Asignación
let x = 10;
x += 5;   // x = 15
x -= 3;   // x = 12
x *= 2;   // x = 24

Estructuras de control

// if / else if / else
if (edad >= 18) {
  console.log("Mayor de edad");
} else if (edad >= 12) {
  console.log("Adolescente");
} else {
  console.log("Niño");
}

// Operador ternario
const mensaje = edad >= 18 ? "Mayor" : "Menor";

// switch
switch (dia) {
  case "lunes":
    console.log("Inicio de semana");
    break;
  case "viernes":
    console.log("¡Por fin viernes!");
    break;
  default:
    console.log("Día entre semana");
}

// Nullish coalescing (??) — devuelve el valor derecho si el izquierdo es null/undefined
const nombre = usuario.nombre ?? "Anónimo";

// Optional chaining (?.) — accede a propiedades sin lanzar error si es null/undefined
const ciudad = usuario?.direccion?.ciudad;

Bucles

// for clásico
for (let i = 0; i < 5; i++) {
  console.log(i);
}

// for...of (iterar valores de un iterable: arrays, strings…)
const frutas = ["manzana", "pera", "uva"];
for (const fruta of frutas) {
  console.log(fruta);
}

// for...in (iterar claves de un objeto)
const persona = { nombre: "Ana", edad: 25 };
for (const clave in persona) {
  console.log(clave, persona[clave]);
}

// while
let contador = 0;
while (contador < 3) {
  console.log(contador);
  contador++;
}

// Métodos de array (preferibles en código funcional)
frutas.forEach(f => console.log(f));
const mayusculas = frutas.map(f => f.toUpperCase());
const largas = frutas.filter(f => f.length > 4);

Funciones

// Declaración clásica (hoisting: se puede llamar antes de definirla)
function saludar(nombre) {
  return `Hola, ${nombre}!`;
}

// Expresión de función
const despedir = function(nombre) {
  return `Adiós, ${nombre}`;
};

// Arrow function (sintaxis moderna, más concisa)
const sumar = (a, b) => a + b;
const cuadrado = n => n * n;  // Paréntesis opcionales con un solo parámetro

// Parámetros por defecto
function conectar(host = "localhost", puerto = 3000) {
  console.log(`Conectando a ${host}:${puerto}`);
}

// Rest parameters (recoge argumentos variables en un array)
function suma(...numeros) {
  return numeros.reduce((acc, n) => acc + n, 0);
}
suma(1, 2, 3, 4); // 10

Desestructuración y Spread

// Desestructuración de arrays
const [primero, segundo, ...resto] = [10, 20, 30, 40];
// primero = 10, segundo = 20, resto = [30, 40]

// Desestructuración de objetos
const { nombre, edad, ciudad = "Madrid" } = persona;

// Spread operator (expandir elementos)
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];           // [1, 2, 3, 4, 5]

const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 };        // { a: 1, b: 2 }

// Muy útil para clonar sin mutar el original
const copia = { ...persona, edad: 26 };

Clases

class Animal {
  #nombre; // Campo privado (ES2022)

  constructor(nombre, sonido) {
    this.#nombre = nombre;
    this.sonido  = sonido;
  }

  hablar() {
    return `${this.#nombre} dice: ${this.sonido}`;
  }

  get nombre() {
    return this.#nombre;
  }
}

class Perro extends Animal {
  constructor(nombre) {
    super(nombre, "¡Guau!");
  }

  buscarPalo() {
    return `${this.nombre} ha encontrado el palo 🐕`;
  }
}

const rex = new Perro("Rex");
console.log(rex.hablar());      // Rex dice: ¡Guau!
console.log(rex.buscarPalo());  // Rex ha encontrado el palo 🐕

Módulos (ES Modules)

// math.js — exportar
export const PI = 3.14159;
export function sumar(a, b) { return a + b; }
export default class Calculadora { /* ... */ }

// main.js — importar
import Calculadora, { PI, sumar } from "./math.js";
import * as Math from "./math.js";  // Importar todo bajo un namespace

3. Paradigmas de programación

JavaScript es multiparadigma: se puede programar de varias formas según el problema.

Imperativo / Procedural

El más básico. Das instrucciones paso a paso que modifican el estado del programa.

let resultado = 0;
for (let i = 1; i <= 5; i++) {
  resultado += i;
}
console.log(resultado); // 15

Orientado a Objetos (OOP)

Organiza el código en objetos con propiedades (datos) y métodos (comportamiento). Soporta los pilares clásicos:

class CuentaBancaria {
  #saldo = 0;

  depositar(cantidad) { this.#saldo += cantidad; }
  retirar(cantidad) {
    if (cantidad > this.#saldo) throw new Error("Saldo insuficiente");
    this.#saldo -= cantidad;
  }
  get saldo() { return this.#saldo; }
}

Funcional (FP)

Trata la computación como evaluación de funciones matemáticas. Principios clave:

// Funciones puras
const doble     = n => n * 2;
const esPar     = n => n % 2 === 0;
const sumarUno  = n => n + 1;

// Operaciones funcionales sobre arrays (no mutan el original)
const numeros = [1, 2, 3, 4, 5, 6];

const resultado = numeros
  .filter(esPar)       // [2, 4, 6]
  .map(doble)          // [4, 8, 12]
  .reduce((acc, n) => acc + n, 0); // 24

// Composición de funciones
const componer = (...fns) => x => fns.reduceRight((v, f) => f(v), x);
const procesarNumero = componer(sumarUno, doble, esPar);

Dirigido por eventos (Event-Driven)

Muy presente en el navegador y en Node.js. El código reacciona a eventos (clicks, peticiones HTTP, mensajes…).

// Navegador
document.getElementById("boton").addEventListener("click", (event) => {
  console.log("Botón pulsado:", event.target);
});

// Node.js (EventEmitter)
const EventEmitter = require("events");
const emisor = new EventEmitter();

emisor.on("datos", (info) => console.log("Recibido:", info));
emisor.emit("datos", { usuario: "Ana" });

4. Programación asíncrona y Promesas

¿Qué es la asincronía en JavaScript?

JavaScript es un lenguaje monohilo: ejecuta una sola tarea a la vez. Sin embargo, muchas operaciones del mundo real llevan tiempo: consultar una base de datos, llamar a una API externa, leer un fichero del disco... Si JavaScript se bloqueara esperando cada una de estas operaciones, la aplicación quedaría congelada.

Para resolver esto, JavaScript incorpora un modelo de ejecución asíncrono: puede iniciar una operación lenta y, mientras espera el resultado, seguir ejecutando otro código. Cuando la operación termina, JavaScript vuelve a ella para procesar el resultado.


Promesas (Promise)

Una promesa es un objeto que representa el resultado eventual (o el fallo) de una operación asíncrona.

Estado Descripción
pending La operación aún no ha terminado
fulfilled La operación terminó con éxito
rejected La operación terminó con un error
const miPromesa = new Promise((resolve, reject) => {
  const exito = true;
  if (exito) {
    resolve("Datos recibidos correctamente");
  } else {
    reject("Ha ocurrido un error");
  }
});

miPromesa
  .then(resultado => console.log(resultado))
  .catch(error    => console.error(error))
  .finally(()     => console.log("Operación finalizada"));

async / await

Sintaxis moderna y legible para trabajar con promesas:

async function obtenerDatos() {
  try {
    const respuesta = await fetch("https://api.ejemplo.com/datos");
    const datos     = await respuesta.json();
    console.log(datos);
  } catch (error) {
    console.error("Error al obtener datos:", error);
  }
}

obtenerDatos();

Promise.all y Promise.race

// Promise.all — espera a que TODAS se resuelvan (o falla si una falla)
const [usuarios, productos] = await Promise.all([
  fetch("/api/usuarios").then(r => r.json()),
  fetch("/api/productos").then(r => r.json()),
]);

// Promise.race — devuelve la primera que se resuelva
const resultado = await Promise.race([
  fetch("/api/rapida"),
  new Promise((_, reject) => setTimeout(() => reject("Timeout"), 5000))
]);

Comparativa: callbacks vs. promesas vs. async/await

// ❌ Callbacks anidados ("callback hell")
getData(function(a) {
  getMoreData(a, function(b) {
    getEvenMoreData(b, function(c) {
      console.log(c);
    });
  });
});

// ✅ Promesas encadenadas
getData()
  .then(a => getMoreData(a))
  .then(b => getEvenMoreData(b))
  .then(c => console.log(c))
  .catch(err => console.error(err));

// ✅✅ async/await (más legible)
async function proceso() {
  const a = await getData();
  const b = await getMoreData(a);
  const c = await getEvenMoreData(b);
  console.log(c);
}

5. Manipulación de Strings: split() y join()

split(separador)

Divide una cadena en un array de subcadenas:

"hola upm".split(' ');   // ["hola", "upm"]
"a,b,c".split(',');      // ["a", "b", "c"]
"abc".split('');         // ["a", "b", "c"]

join(separador)

Une los elementos de un array en una cadena:

["hola", "upm"].join('');   // "holaupm"
["hola", "upm"].join(' ');  // "hola upm"
["hola", "upm"].join('-');  // "hola-upm"

Encadenamiento y casos de uso

// Invertir una cadena
"JavaScript".split('').reverse().join('');
// → "tpircSavaJ"

// Eliminar espacios duplicados
"hola   mundo".split(' ').filter(Boolean).join(' ');
// → "hola mundo"

// CSV ↔ array
const csv     = "Madrid,Barcelona,Valencia";
const ciudades = csv.split(',');
const nuevo   = ciudades.join(' | ');  // "Madrid | Barcelona | Valencia"

6. Ecosistema: Node.js

¿Qué es Node.js?

Node.js es un entorno de ejecución de JavaScript fuera del navegador, construido sobre el motor V8 de Chrome. Permite usar JavaScript en el servidor para crear APIs, scripts de automatización, herramientas CLI, etc.

Navegador              Node.js
──────────────         ──────────────────
JS + DOM API           JS + APIs del sistema
window, document       fs, http, path, os…
Limitado al sandbox    Acceso total al SO

Instalación

Descarga el instalador desde nodejs.org o usa un gestor de versiones:

# Con nvm (Node Version Manager) — recomendado
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
nvm install --lts       # Instala la versión LTS más reciente
nvm use --lts

# Comprobar versiones
node --version   # v22.x.x
npm --version    # 10.x.x

Módulos integrados de Node.js

// Módulo fs (sistema de ficheros)
const fs = require("fs");
const contenido = fs.readFileSync("archivo.txt", "utf8");

// Con promesas (fs/promises)
import { readFile, writeFile } from "fs/promises";
const texto = await readFile("archivo.txt", "utf8");

// Módulo http (servidor HTTP básico)
const http = require("http");
const servidor = http.createServer((req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("¡Hola desde Node.js!");
});
servidor.listen(3000, () => console.log("Servidor en http://localhost:3000"));

// Módulo path
const path = require("path");
const ruta = path.join(__dirname, "src", "index.js");

// Módulo os
const os = require("os");
console.log(os.platform(), os.cpus().length);
npm install express
import express from "express";
const app = express();

app.use(express.json()); // Parsear JSON en el body

app.get("/usuarios", (req, res) => {
  res.json([{ id: 1, nombre: "Ana" }]);
});

app.post("/usuarios", (req, res) => {
  const { nombre } = req.body;
  res.status(201).json({ id: 2, nombre });
});

app.listen(3000, () => console.log("API lista en http://localhost:3000"));

7. Gestión de paquetes: npm, pnpm y yarn

Un gestor de paquetes permite instalar, actualizar y gestionar las dependencias de tu proyecto (librerías de terceros).

package.json — el corazón del proyecto

{
  "name": "mi-proyecto",
  "version": "1.0.0",
  "scripts": {
    "dev":   "vite",
    "build": "vite build",
    "test":  "jest"
  },
  "dependencies": {
    "react": "^18.3.0",
    "axios": "^1.7.0"
  },
  "devDependencies": {
    "vite": "^5.0.0",
    "jest": "^29.0.0"
  }
}

npm (Node Package Manager)

Viene incluido con Node.js. Es el gestor más extendido.

# Inicializar un proyecto
npm init -y

# Instalar una dependencia
npm install react
npm install react --save-dev     # Solo desarrollo
npm install                      # Instalar todo lo de package.json

# Actualizar / desinstalar
npm update axios
npm uninstall lodash

# Ejecutar scripts definidos en package.json
npm run dev
npm run build
npm test

# Ver paquetes instalados globalmente
npm list -g --depth=0

pnpm (Performant npm)

Alternativa a npm mucho más rápida y eficiente en disco. Usa un almacén global con hardlinks en lugar de copiar paquetes en cada proyecto.

# Instalar pnpm
npm install -g pnpm

# Uso (la API es casi idéntica a npm)
pnpm init
pnpm install react
pnpm add axios
pnpm add -D vite        # Dependencia de desarrollo
pnpm remove lodash
pnpm run dev

yarn

Otra alternativa popular, especialmente en proyectos React/monorepos.

# Instalar yarn
npm install -g yarn

# Uso
yarn init
yarn add react
yarn add --dev eslint
yarn remove lodash
yarn dev                # Equivale a npm run dev

Comparativa rápida

Característica npm pnpm yarn
Velocidad Buena ⚡ Muy alta Alta
Espacio en disco Alto ⚡ Muy bajo Medio
Compatibilidad Universal Alta Alta
Monorepos Básico Excelente Bueno (workspaces)
Incluido con Node ✅ Sí ❌ (instalar aparte) ❌ (instalar aparte)

8. Frameworks y librerías principales

React

La librería de UI más popular, creada por Meta. Basada en componentes reutilizables y un DOM virtual para actualizaciones eficientes.

# Crear proyecto con Vite (recomendado)
pnpm create vite mi-app --template react
cd mi-app && pnpm install && pnpm dev

# O con Create React App (más pesado, menos usado hoy)
npx create-react-app mi-app
// Componente funcional con hooks
import { useState, useEffect } from "react";

function Contador({ inicio = 0 }) {
  const [cuenta, setCuenta] = useState(inicio);

  useEffect(() => {
    document.title = `Cuenta: ${cuenta}`;
  }, [cuenta]); // Se ejecuta cada vez que cambia `cuenta`

  return (
    <div>
      <p>Cuenta: {cuenta}</p>
      <button onClick={() => setCuenta(c => c + 1)}>+</button>
      <button onClick={() => setCuenta(c => c - 1)}>-</button>
    </div>
  );
}

export default Contador;

Hooks más comunes:

Hook Para qué sirve
useState Estado local del componente
useEffect Efectos secundarios (fetch, timers, DOM…)
useContext Consumir contexto global
useRef Referenciar elementos del DOM
useMemo Memorizar cálculos costosos
useCallback Memorizar funciones

Angular

Framework completo mantenido por Google. Ideal para aplicaciones empresariales grandes. Usa TypeScript por defecto.

npm install -g @angular/cli
ng new mi-app
cd mi-app && ng serve
// Componente Angular
import { Component, OnInit } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Component({
  selector:    "app-usuarios",
  template: `
    <ul>
      <li *ngFor="let u of usuarios">{{ u.nombre }}</li>
    </ul>
  `
})
export class UsuariosComponent implements OnInit {
  usuarios: any[] = [];

  constructor(private http: HttpClient) {}

  ngOnInit() {
    this.http.get<any[]>("/api/usuarios").subscribe(data => {
      this.usuarios = data;
    });
  }
}

Vue.js

Framework progresivo: se puede añadir de forma incremental a un proyecto existente. Muy buena curva de aprendizaje.

pnpm create vue@latest mi-app
cd mi-app && pnpm install && pnpm dev
<script setup>
import { ref, onMounted } from "vue";

const usuarios = ref([]);

onMounted(async () => {
  const res = await fetch("/api/usuarios");
  usuarios.value = await res.json();
});
</script>

<template>
  <ul>
    <li v-for="u in usuarios" :key="u.id">{{ u.nombre }}</li>
  </ul>
</template>

Next.js

Framework full-stack sobre React. Añade Server-Side Rendering (SSR), generación estática (SSG), routing basado en ficheros, API Routes y más.

npx create-next-app@latest mi-app
cd mi-app && npm run dev
// app/page.jsx — Server Component (se ejecuta en el servidor)
async function Inicio() {
  const datos = await fetch("https://api.ejemplo.com/posts").then(r => r.json());

  return (
    <main>
      {datos.map(post => (
        <article key={post.id}>
          <h2>{post.titulo}</h2>
        </article>
      ))}
    </main>
  );
}

export default Inicio;

Bootstrap

La librería de CSS y componentes UI más usada históricamente. Permite crear interfaces responsivas rápidamente con clases predefinidas.

npm install bootstrap
<!-- En HTML puro -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">

<div class="container mt-4">
  <div class="row">
    <div class="col-md-6">
      <div class="card">
        <div class="card-body">
          <h5 class="card-title">Título</h5>
          <button class="btn btn-primary">Acción</button>
        </div>
      </div>
    </div>
  </div>
</div>
// En React con react-bootstrap
import { Button, Card } from "react-bootstrap";
import "bootstrap/dist/css/bootstrap.min.css";

function MiTarjeta() {
  return (
    <Card style={{ width: "18rem" }}>
      <Card.Body>
        <Card.Title>Título</Card.Title>
        <Button variant="primary">Acción</Button>
      </Card.Body>
    </Card>
  );
}

Otras librerías relevantes

Librería Categoría Para qué sirve
Axios HTTP Peticiones HTTP más cómodas que fetch
Lodash Utilidades Funciones de manipulación de arrays, objetos, strings
date-fns / dayjs Fechas Manipulación y formateo de fechas
Zod Validación Esquemas y validación de tipos en runtime
Zustand / Redux Estado global Gestión del estado en apps React
React Query Data fetching Cache y sincronización de datos del servidor
Socket.io Tiempo real WebSockets simplificados
Jest / Vitest Testing Tests unitarios y de integración
ESLint / Prettier Calidad código Linting y formateo automático

9. Herramientas de construcción (Build Tools)

Las aplicaciones modernas de JavaScript necesitan ser transformadas antes de llegar al navegador: transpilar TypeScript/JSX, empaquetar módulos, minificar código, etc.

Vite

El bundler más popular actualmente. Extremadamente rápido gracias al uso de ES Modules nativos durante el desarrollo.

# Crear proyecto (elige tu framework en el asistente)
pnpm create vite mi-app
cd mi-app && pnpm install

# Comandos
pnpm dev      # Servidor de desarrollo (HMR instantáneo)
pnpm build    # Construir para producción (usa Rollup internamente)
pnpm preview  # Previsualizar el build de producción
// vite.config.js
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  server: {
    port: 4000,
    proxy: {
      "/api": "http://localhost:3000" // Proxy para el backend
    }
  }
});

Webpack

El bundler más veterano y flexible. Tiene una configuración más compleja, pero es muy potente. Next.js lo usa internamente (migrando a Turbopack).

npm install --save-dev webpack webpack-cli
// webpack.config.js (configuración básica)
const path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js",
  },
  module: {
    rules: [
      { test: /\.jsx?$/, use: "babel-loader", exclude: /node_modules/ },
      { test: /\.css$/,  use: ["style-loader", "css-loader"] },
    ],
  },
};

TypeScript

Superset de JavaScript que añade tipado estático. Detecta errores en tiempo de compilación, no en ejecución.

pnpm add -D typescript
npx tsc --init   # Genera tsconfig.json
// Tipos básicos
let nombre: string     = "Ana";
let edad:   number     = 25;
let activo: boolean    = true;
let lista:  number[]   = [1, 2, 3];

// Interfaces y tipos
interface Usuario {
  id:       number;
  nombre:   string;
  email?:   string;  // Propiedad opcional
}

type Resultado<T> = {
  datos:  T;
  error:  string | null;
  exito:  boolean;
};

// Función tipada
async function obtenerUsuario(id: number): Promise<Usuario> {
  const res = await fetch(`/api/usuarios/${id}`);
  return res.json() as Promise<Usuario>;
}

10. Resumen general

Concepto Idea clave
JavaScript Lenguaje interpretado, dinámico y multiparadigma
let / const Variables modernas con ámbito de bloque
Arrow functions Sintaxis concisa para funciones: (a, b) => a + b
Desestructuración Extraer valores de arrays/objetos fácilmente
Spread operator Expandir iterables: [...arr], {...obj}
Promesas Representan el resultado futuro de una operación asíncrona
async/await Sintaxis moderna para consumir promesas de forma legible
split / join Convertir strings ↔ arrays
Node.js JS en el servidor; acceso a ficheros, red, SO…
npm / pnpm / yarn Gestores de paquetes para instalar dependencias
React Librería de UI basada en componentes y hooks
Angular Framework completo para apps empresariales (TypeScript)
Vue.js Framework progresivo con excelente DX
Next.js Full-stack con React: SSR, SSG, routing y API routes
Bootstrap Librería CSS de componentes responsivos listos para usar
Vite Bundler moderno: desarrollo instantáneo, build optimizado
TypeScript JS con tipado estático; detecta errores en compilación
Paradigmas Imperativo, OOP, Funcional y Event-Driven