Módulo 01: Entorno de desarrollo

Objetivos del módulo

  • Usar la consola de las DevTools del navegador para ejecutar código y depurar
  • Conocer los métodos de console: log, info, warn, error, table, group, time, dir y otros
  • Preparar Visual Studio Code con las extensiones más útiles para JavaScript
  • Incluir JavaScript en una página HTML de todas las formas posibles y entender defer, async y type="module"
  • Instalar Node.js 24 LTS, usar su REPL y ejecutar ficheros .js y .mjs
  • Conocer las diferencias entre ejecutar JavaScript en el navegador y en Node.js
  • Organizar la estructura de un primer proyecto
  • Escribir tu primer programa en el navegador y en Node.js
  • Depurar con breakpoints y con la instrucción debugger
  • Entender el modo estricto y por qué los módulos ya lo activan

1. El navegador: tu primer entorno

No necesitas instalar nada para empezar: cualquier navegador moderno trae un motor de JavaScript y unas herramientas para desarrolladores (las DevTools). En este curso usaremos sobre todo Chrome o Edge (que comparten herramientas casi idénticas) y Firefox, pero todo funciona igual en Safari.

1.1 Abrir las DevTools

Navegador Abrir DevTools Ir directamente a la consola
Chrome / Edge (Windows, Linux) F12 o Ctrl + Mayús + I Ctrl + Mayús + J
Chrome / Edge (macOS) Cmd + Option + I Cmd + Option + J
Firefox (Windows, Linux) F12 o Ctrl + Mayús + I Ctrl + Mayús + K
Firefox (macOS) Cmd + Option + I Cmd + Option + K
Safari (macOS) Primero activa Ajustes → Avanzado → Mostrar funciones para desarrolladores web Cmd + Option + C

También puedes hacer clic derecho sobre cualquier parte de una página y elegir Inspeccionar.

Las DevTools tienen varios paneles. Estos son los que más usarás:

Panel (Chrome) Panel (Firefox) Para qué sirve
Elements Inspector Ver y editar el HTML y el CSS de la página en vivo
Console Consola Ver mensajes y errores, y ejecutar JavaScript
Sources Depurador Ver los ficheros JavaScript, poner breakpoints y depurar
Network Red Ver cada petición que hace la página (HTML, imágenes, datos…)
Application Almacenamiento Ver localStorage, cookies, caché…

1.2 Ejecutar código en la consola

La consola es un REPL (Read-Eval-Print Loop): lee lo que escribes, lo evalúa, imprime el resultado y vuelve a esperar. Es perfecta para probar cosas rápidamente.

✏️ Ejercicio: Abre la consola en una pestaña en blanco (about:blank) y escribe, pulsando Intro después de cada línea:

2 + 3
'Hola' + ' ' + 'mundo'
Math.max(4, 17, 9)
new Date().getFullYear()

Verás que después de cada línea aparece el resultado. Algunos trucos de la consola:

Acción Cómo
Ejecutar Intro
Escribir varias líneas sin ejecutar Mayús + Intro
Recuperar instrucciones anteriores Flechas ↑ y ↓
Autocompletar Tab o → cuando aparece la sugerencia
Limpiar la consola Ctrl + L o escribir clear()
Último elemento seleccionado en Elements $0

⚠️ Importante: La primera vez que intentes pegar código en la consola de Chrome, te pedirá que escribas allow pasting (o su equivalente en español). Es una protección contra estafas: algunos timadores piden a sus víctimas que peguen código en la consola para robarles la sesión. Nunca pegues en la consola código que te envíe un desconocido.

💡 Consejo: Lo que escribes en la consola se pierde al recargar la página. Para trozos de código más largos, en Chrome tienes Sources → Snippets: pequeños scripts que se guardan en el navegador y que puedes ejecutar con Ctrl + Intro.

1.3 El objeto console

console es un objeto con muchos métodos para mostrar información. Aunque no forma parte de ECMAScript (es una API del entorno), está en todos los navegadores y en Node.js.

Mensajes básicos: log, info, warn, error

console.log('Mensaje normal');
console.info('Información');      // en Chrome se ve igual que log
console.warn('Cuidado: stock bajo'); // fondo amarillo y icono de advertencia
console.error('No se pudo guardar'); // fondo rojo y se cuenta como error

// Puedes pasar varios valores separados por comas
const nombre = 'Ana';
const edad = 28;
console.log('Usuario:', nombre, 'Edad:', edad);
// Usuario: Ana Edad: 28

💡 Consejo: La consola permite filtrar por nivel (Errores, Advertencias, Información…). Usar warn y error en vez de log para los problemas te permite encontrarlos rápido entre cientos de mensajes. En Node.js, console.error y console.warn escriben en la salida de errores (stderr) y console.log en la salida normal (stdout).

console.table: datos en forma de tabla

const usuarios = [
  { nombre: 'Ana', edad: 28, ciudad: 'Madrid' },
  { nombre: 'Luis', edad: 34, ciudad: 'Sevilla' },
  { nombre: 'Marta', edad: 22, ciudad: 'Valencia' },
];

console.table(usuarios);
// Salida en Node.js (en el navegador se ve como una tabla con estilo):
// ┌─────────┬─────────┬──────┬────────────┐
// │ (index) │ nombre  │ edad │ ciudad     │
// ├─────────┼─────────┼──────┼────────────┤
// │ 0       │ 'Ana'   │ 28   │ 'Madrid'   │
// │ 1       │ 'Luis'  │ 34   │ 'Sevilla'  │
// │ 2       │ 'Marta' │ 22   │ 'Valencia' │
// └─────────┴─────────┴──────┴────────────┘

console.table(usuarios, ['nombre', 'ciudad']); // solo esas columnas

console.group: agrupar mensajes

console.group('Pedido 1042');
console.log('Cliente: Ana');
console.group('Productos');
console.log('Teclado x1');
console.log('Ratón x2');
console.groupEnd();
console.log('Total: 59,90 €');
console.groupEnd();

// Salida:
// Pedido 1042
//   Cliente: Ana
//   Productos
//     Teclado x1
//     Ratón x2
//   Total: 59,90 €

En el navegador, cada grupo se puede plegar y desplegar. console.groupCollapsed() crea el grupo ya plegado.

console.time: medir cuánto tarda algo

console.time('bucle');
let suma = 0;
for (let i = 0; i < 1_000_000; i++) {
  suma += i;
}
console.timeEnd('bucle');
// bucle: 6.555ms   (el número variará en tu ordenador)

La etiqueta ('bucle') debe ser la misma en time y timeEnd. Con console.timeLog('bucle') puedes ver el tiempo parcial sin detener el cronómetro.

console.dir: inspeccionar objetos

const config = {
  servidor: { host: 'localhost', puerto: 3000, opciones: { ssl: { activo: false } } },
};

console.log(config);
// En Node.js, a partir de cierta profundidad muestra [Object]:
// { servidor: { host: 'localhost', puerto: 3000, opciones: { ssl: [Object] } } }

console.dir(config, { depth: null }); // depth: null = sin límite (opción de Node.js)

En el navegador, console.dir muestra el objeto como un árbol desplegable de propiedades. Es especialmente útil con elementos de la página: console.log(document.body) muestra el HTML, mientras que console.dir(document.body) muestra el objeto JavaScript con todas sus propiedades.

Otros métodos útiles

console.count('clic'); // clic: 1
console.count('clic'); // clic: 2   (cuenta cuántas veces se llama)

console.assert(1 + 1 === 3, 'Las matemáticas han fallado');
// Assertion failed: Las matemáticas han fallado   (solo si la condición es falsa)

console.log('Nombre: %s, edad: %d', 'Ana', 28); // sustituciones al estilo C
// Nombre: Ana, edad: 28

// Solo en el navegador: dar estilos CSS con %c
console.log('%c¡Hola!', 'color: white; background: purple; font-size: 20px; padding: 4px;');
Método Uso
console.log() Mensaje general
console.info() Información (nivel “info”)
console.warn() Advertencia
console.error() Error
console.table() Arrays y objetos como tabla
console.group() / groupCollapsed() / groupEnd() Agrupar mensajes
console.time() / timeLog() / timeEnd() Medir tiempos
console.dir() Inspeccionar las propiedades de un objeto
console.count() Contar llamadas
console.assert() Mostrar un error solo si una condición es falsa
console.clear() Limpiar la consola

⚠️ Importante: Los console.log son para desarrollar, no para producción. Antes de publicar una web, elimina los mensajes de depuración (ESLint puede avisarte de ellos, como verás en el módulo 21).


2. Visual Studio Code

La consola está bien para pruebas, pero los programas de verdad se escriben en ficheros con un editor de código. El más usado para JavaScript es Visual Studio Code (VS Code), gratuito y disponible para Windows, macOS y Linux. Descárgalo de code.visualstudio.com.

📘 Concepto: VS Code es un editor, no un entorno de ejecución: te ayuda a escribir código (colores, autocompletado, avisos de errores), pero para ejecutarlo necesitas un navegador o Node.js. Curiosamente, VS Code está hecho con JavaScript y TypeScript sobre Electron.

2.1 Extensiones recomendadas

Abre el panel de extensiones con Ctrl + Mayús + X y busca:

Extensión Identificador Para qué sirve
ESLint (Microsoft) dbaeumer.vscode-eslint Analiza tu código y marca errores y malas prácticas mientras escribes
Prettier - Code formatter esbenp.prettier-vscode Formatea el código automáticamente (sangrías, comillas, espacios)
Live Server (Ritwick Dey) ritwickdey.LiveServer Sirve tu carpeta en un servidor local y recarga el navegador al guardar
Live Preview (Microsoft) ms-vscode.live-server Alternativa oficial a Live Server, con vista previa dentro del editor
Error Lens usernamehw.errorlens Muestra los errores en la misma línea, sin pasar el ratón
Paquete de idioma español MS-CEINTL.vscode-language-pack-es Interfaz de VS Code en español

También puedes instalarlas desde la terminal:

code --install-extension dbaeumer.vscode-eslint
code --install-extension esbenp.prettier-vscode
code --install-extension ritwickdey.LiveServer

💡 Consejo: ESLint y Prettier funcionan mejor cuando el proyecto tiene su propia configuración (eslint.config.js, .prettierrc). En el módulo 21 los configurarás a fondo. Por ahora basta con que estén instalados.

2.2 Ajustes útiles

Abre la configuración en formato JSON con Ctrl + Mayús + P → Preferences: Open User Settings (JSON) y añade:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.tabSize": 2,
  "files.autoSave": "onFocusChange",
  "editor.bracketPairColorization.enabled": true
}

2.3 Atajos imprescindibles

Atajo Acción
Ctrl + Mayús + P Paleta de comandos (desde aquí se hace todo)
Ctrl + P Abrir un fichero por su nombre
Ctrl + ñ (teclado español) o Ctrl + ` Abrir/cerrar la terminal integrada
Ctrl + / Comentar/descomentar líneas
Alt + ↑ / Alt + ↓ Mover la línea actual
Mayús + Alt + ↓ Duplicar la línea
Ctrl + D Seleccionar la siguiente aparición de la palabra (multicursor)
F2 Renombrar una variable en todo el fichero
Mayús + Alt + F Formatear el documento
! + Tab en un .html Generar el esqueleto HTML5 (Emmet)

3. JavaScript dentro de una página HTML

El navegador ejecuta JavaScript cuando encuentra una etiqueta <script> en el HTML. Hay varias formas de usarla.

3.1 Script en línea

El código va directamente entre <script> y </script>:

<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Script en línea</title>
</head>
<body>
  <h1>Hola</h1>
  <script>
    console.log('Este código está dentro del HTML');
  </script>
</body>
</html>

Útil para pruebas rápidas, pero no para proyectos: mezcla contenido y comportamiento, no se puede reutilizar en otras páginas y el navegador no lo puede guardar en caché por separado.

3.2 Script externo

El código va en un fichero .js aparte y se enlaza con el atributo src:

<script src="js/main.js"></script>
// js/main.js
console.log('Este código está en un fichero externo');

⚠️ Importante: Si una etiqueta <script> tiene src, el código que escribas dentro de ella se ignora. Usa una etiqueta para cada cosa.

3.3 La posición importa

El navegador lee el HTML de arriba abajo. Por defecto, cuando encuentra un <script> clásico se detiene, descarga el fichero, lo ejecuta y solo entonces continúa leyendo el HTML. Esto tiene dos consecuencias:

  1. Si el script está en el <head>, la página se queda en blanco mientras se descarga y ejecuta.
  2. Si el script intenta acceder a un elemento que aparece más abajo, ese elemento todavía no existe.
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <title>Error típico</title>
  <script>
    // ❌ El párrafo aún no existe: devuelve null
    const parrafo = document.querySelector('#saludo');
    console.log(parrafo); // null
  </script>
</head>
<body>
  <p id="saludo">Hola</p>
</body>
</html>

La solución antigua era poner los scripts justo antes de </body>. La solución moderna es usar defer o type="module" en el <head>.

3.4 Los atributos defer, async y type="module"

Forma ¿Bloquea el HTML mientras se descarga? ¿Cuándo se ejecuta? ¿Respeta el orden entre scripts?
<script src> (clásico) Sí Nada más descargarse Sí
<script src defer> No Cuando el HTML se ha leído entero, antes del evento DOMContentLoaded Sí
<script src async> No (se descarga en paralelo) En cuanto termina de descargarse, interrumpiendo el análisis del HTML No
<script type="module"> No Como defer (diferido por defecto) Sí
<script type="module" async> No Como async No
Leyenda:  ███ análisis del HTML   ↓↓↓ descarga del script   ▓▓▓ ejecución

Clásico:   ███████|↓↓↓↓↓↓|▓▓▓|████████████
                   ^ el análisis del HTML se detiene

defer:     ████████████████████████████|▓▓▓
               ↓↓↓↓↓↓ (en paralelo)       ^ se ejecuta al terminar el HTML

async:     █████████████|▓▓▓|█████████████
               ↓↓↓↓↓↓↓↓↓  ^ se ejecuta en cuanto llega (interrumpe)

module:    ████████████████████████████|▓▓▓
               ↓↓↓↓↓↓ (+ sus dependencias)  ^ igual que defer
flowchart TD
    A["¿El script necesita el HTML<br/>o depende de otros scripts?"] -->|Sí| B["type=module<br/>(o defer si no es módulo)"]
    A -->|No: es independiente,<br/>p. ej. analítica| C["async"]

📘 Concepto: Un módulo (type="module") es la forma moderna de escribir JavaScript: puede usar import y export para dividir el código en ficheros, tiene su propio ámbito (sus variables no “contaminan” la página), se ejecuta siempre en modo estricto y se difiere automáticamente. Es lo que usaremos en todo el curso. Lo estudiarás a fondo en el módulo 13.

💡 Consejo: La receta profesional para casi todos los casos es: <script type="module" src="js/main.js"></script> dentro del <head>. No bloquea la página, se ejecuta cuando el HTML ya está listo y te permite usar import.

3.5 Los módulos necesitan un servidor

Si abres un HTML haciendo doble clic, la dirección empieza por file://. Los navegadores bloquean la carga de módulos externos desde file:// por motivos de seguridad (política CORS) y verás un error como este en la consola:

Access to script at 'file:///C:/.../js/main.js' from origin 'null' has been blocked by CORS policy

La solución es servir la carpeta con un servidor local:

  • En VS Code: clic derecho sobre el index.html → Open with Live Server (o el botón Go Live de la barra inferior). Se abrirá en una dirección como http://127.0.0.1:5500.
  • Con Node.js instalado: npx serve en la carpeta del proyecto (descarga y ejecuta un pequeño servidor).

3.6 Atributos menos usados

  • nomodule: el script solo se ejecuta en navegadores antiguos que no entienden módulos. Hoy apenas se usa.
  • <noscript>: contenido que se muestra solo si JavaScript está desactivado.
  • crossorigin e integrity: para cargar scripts de otros dominios (CDN) de forma segura. Los verás al usar bibliotecas externas.

4. Node.js 24 LTS

Node.js es un entorno para ejecutar JavaScript fuera del navegador, directamente en tu ordenador. Lo necesitarás para muchos ejemplos del curso y para las herramientas profesionales (npm, Vite, ESLint, Vitest).

4.1 Versiones: Current y LTS

📘 Concepto: LTS significa Long Term Support (soporte a largo plazo). Las versiones LTS reciben correcciones de errores y de seguridad durante años, por eso son las que se usan en empresas y en este curso.

Versión Estado (octubre de 2026)
Node.js 24 Active LTS: la recomendada para este curso
Node.js 26 Current; pasa a LTS el 28 de octubre de 2026
Node.js 22 Maintenance LTS: solo correcciones críticas

Tradicionalmente salían dos versiones mayores al año y solo las pares llegaban a LTS. A partir de Node.js 27 el proyecto pasa a publicar una única versión mayor al año. Todo el código del curso funciona en Node.js 24 y posteriores.

4.2 Instalación en Windows

Opción A: instalador oficial (la más sencilla)

  1. Entra en nodejs.org y descarga el instalador LTS para Windows (.msi).
  2. Ejecútalo y acepta las opciones por defecto (incluye npm, el gestor de paquetes).
  3. Cierra y vuelve a abrir la terminal.

También puedes instalarlo con el gestor de paquetes de Windows:

winget install OpenJS.NodeJS.LTS

Opción B: un gestor de versiones (recomendada a medio plazo)

Un gestor de versiones te permite tener varias versiones de Node.js instaladas y cambiar entre ellas, algo muy habitual cuando trabajas en proyectos distintos.

Con nvm-windows:

winget install CoreyButler.NVMforWindows
# Cierra y abre la terminal, después:
nvm install 24
nvm use 24
nvm list          # versiones instaladas

Con fnm (Fast Node Manager, multiplataforma):

winget install Schniz.fnm
# Añade esta línea a tu perfil de PowerShell (notepad $PROFILE) para activarlo:
# fnm env --use-on-cd --shell powershell | Out-String | Invoke-Expression
fnm install 24
fnm use 24
fnm default 24

4.3 Instalación en macOS y Linux

Puedes usar el instalador de nodejs.org, pero lo más habitual es nvm. Sigue las instrucciones de instalación de su repositorio oficial (github.com/nvm-sh/nvm) y después:

nvm install 24
nvm use 24
nvm alias default 24

⚠️ Importante: No mezcles métodos. Si instalas Node.js con el instalador oficial y además con un gestor de versiones, tendrás dos copias peleándose. Elige uno.

4.4 Comprobar la instalación

node -v
# v24.19.0   (o la versión 24.x que tengas)
npm -v
# 11.x.x

Si aparece “node no se reconoce como un comando”, cierra todas las terminales (y VS Code) y vuelve a abrirlas para que se actualice la variable PATH.

4.5 El REPL de Node.js

Igual que la consola del navegador, Node.js tiene un REPL. Escribe node sin argumentos:

PS C:\> node
Welcome to Node.js v24.19.0.
Type ".help" for more information.
> 2 + 3
5
> const nombre = 'Ana'
undefined
> `Hola, ${nombre}`
'Hola, Ana'
> _.length
9
> .exit
Comando del REPL Qué hace
.help Lista de comandos
.editor Modo editor para escribir varias líneas (termina con Ctrl + D)
.exit o Ctrl + D Salir (también Ctrl + C dos veces)
_ El resultado de la última expresión
Tab Autocompletar

📘 Concepto: ¿Por qué aparece undefined después de const nombre = 'Ana'? Porque el REPL siempre muestra el valor de lo que ejecutas, y una declaración de variable no produce ningún valor. No es un error.

4.6 Ejecutar ficheros: .js y .mjs

Crea un fichero hola.mjs:

// hola.mjs
console.log('¡Hola desde Node.js!');
console.log(`Versión de Node: ${process.version}`);

Y ejecútalo desde la terminal, en la carpeta del fichero:

node hola.mjs
# ¡Hola desde Node.js!
# Versión de Node: v24.19.0

Node.js tiene dos sistemas de módulos: el moderno y estándar, ES Modules (import/export), y el antiguo propio de Node, CommonJS (require/module.exports). La extensión del fichero y el package.json deciden cuál se usa:

Fichero Se trata como
.mjs Siempre módulo ES
.cjs Siempre CommonJS
.js con "type": "module" en el package.json Módulo ES
.js sin "type" CommonJS… salvo que Node detecte sintaxis import/export, en cuyo caso lo reinterpreta como módulo ES (y puede mostrar un aviso)

💡 Consejo: En este curso usaremos módulos ES. Para ejemplos sueltos, usa la extensión .mjs. En proyectos, crea un package.json con "type": "module" y usa .js normal (lo verás en la sección 6).

4.7 node --watch: reejecutar al guardar

Mientras programas, es pesado volver a escribir node fichero tras cada cambio. Con --watch, Node.js vigila el fichero y lo reejecuta automáticamente cada vez que guardas:

node --watch hola.mjs

Para salir, pulsa Ctrl + C.

4.8 Otras formas útiles de usar node

node -e "console.log(2 ** 10)"   # ejecuta el código del texto: 1024
node -p "Math.PI.toFixed(4)"     # ejecuta e imprime el resultado: 3.1416
node --run dev                   # ejecuta el script "dev" del package.json

5. Navegador frente a Node.js

El lenguaje es el mismo, pero el entorno cambia lo que puedes hacer:

Característica Navegador Node.js
Objeto global window (también globalThis) globalThis (también global)
Página web (DOM) Sí: document, elementos, eventos No existe
alert, prompt, confirm Sí No
Acceso a ficheros del disco No (solo si el usuario elige uno) Sí, con node:fs
Información del proceso No process (argumentos, variables de entorno…)
Peticiones de red fetch fetch (y módulos node:http, node:https)
Módulos <script type="module">, import por URL Módulos ES y CommonJS, import de paquetes npm
Dónde sale console.log Consola de DevTools La terminal
Seguridad Muy restringido (sandbox) Acceso completo al sistema (con los permisos de tu usuario)
// Este código funciona en ambos entornos
console.log(typeof globalThis); // object

// ¿Dónde estoy?
if (typeof window !== 'undefined') {
  console.log('Estoy en un navegador');
} else if (typeof process !== 'undefined') {
  console.log('Estoy en Node.js');
}

💡 Consejo: globalThis (ES2020) es la forma estándar de acceder al objeto global en cualquier entorno. Si alguna vez necesitas el objeto global, usa globalThis en lugar de window o global.


6. Estructura de un primer proyecto

Mantener el proyecto ordenado desde el principio es un hábito profesional. Crea una carpeta para tus prácticas del curso, por ejemplo C:\cursos\javascript\, y dentro una carpeta por proyecto.

6.1 Proyecto para el navegador

mi-primera-web/
├── index.html        ← la página principal
├── css/
│   └── estilos.css   ← el diseño
└── js/
    └── main.js       ← el comportamiento (punto de entrada)

6.2 Proyecto para Node.js

mi-primer-script/
├── package.json      ← descripción del proyecto
└── src/
    └── index.js      ← punto de entrada

El package.json se crea con npm:

mkdir mi-primer-script
cd mi-primer-script
npm init -y              # crea un package.json con valores por defecto
npm pkg set type=module  # añade "type": "module"
{
  "name": "mi-primer-script",
  "version": "1.0.0",
  "type": "module",
  "main": "index.js",
  "scripts": {
    "start": "node src/index.js",
    "dev": "node --watch src/index.js"
  }
}

📘 Concepto: El package.json es el “carné de identidad” de un proyecto de JavaScript: nombre, versión, tipo de módulos, scripts que puedes lanzar (npm run dev o node --run dev) y dependencias. Lo estudiarás a fondo en el módulo 20. El contenido que genera npm init -y incluye algunos campos más (description, license…); el scripts de arriba lo añades tú.

6.3 Nombres de ficheros y carpetas

  • Usa minúsculas y guiones: lista-tareas.js, no Lista Tareas.js.
  • Sin espacios, tildes ni eñes en nombres de ficheros: dan problemas en URLs y servidores.
  • El fichero principal suele llamarse main.js o index.js.

7. Tu primer programa

7.1 En el navegador

💻 Ejemplo: Una página que te saluda por tu nombre y te dice cuántos días faltan para fin de año.

<!-- mi-primera-web/index.html -->
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Mi primer programa</title>
  <link rel="stylesheet" href="css/estilos.css">
  <script type="module" src="js/main.js"></script>
</head>
<body>
  <h1 id="titulo">Cargando...</h1>
  <p id="info"></p>
</body>
</html>
/* mi-primera-web/css/estilos.css */
body {
  font-family: system-ui, sans-serif;
  max-width: 40rem;
  margin: 2rem auto;
  padding: 0 1rem;
}

h1 {
  color: rebeccapurple;
}
// mi-primera-web/js/main.js
const nombre = prompt('¿Cómo te llamas?') || 'desconocido';

const hoy = new Date();
const finDeAnio = new Date(hoy.getFullYear(), 11, 31); // los meses empiezan en 0: 11 = diciembre
const msPorDia = 1000 * 60 * 60 * 24;
const diasRestantes = Math.ceil((finDeAnio - hoy) / msPorDia);

document.querySelector('#titulo').textContent = `¡Hola, ${nombre}!`;
document.querySelector('#info').textContent = `Faltan ${diasRestantes} días para fin de año.`;

console.log('Programa ejecutado correctamente');

Ábrelo con Live Server y comprueba también la consola de las DevTools.

📘 Concepto: Fíjate en que el script está en el <head> y aun así encuentra #titulo: como es un módulo, espera a que el HTML esté completo antes de ejecutarse.

7.2 En Node.js

💻 Ejemplo: Un programa que recibe tu nombre desde la línea de comandos.

// mi-primer-script/src/index.js
import os from 'node:os';

// process.argv contiene: [ruta de node, ruta del script, ...argumentos]
const nombre = process.argv[2] ?? 'desconocido';

console.log(`¡Hola, ${nombre}!`);
console.log(`Sistema operativo: ${os.platform()}`);
console.log(`Usuario: ${os.userInfo().username}`);
console.log(`Node.js ${process.version}`);
node src/index.js Ana
# ¡Hola, Ana!
# Sistema operativo: win32
# Usuario: Fran
# Node.js v24.19.0

✏️ Ejercicio: Ejecuta el programa sin argumento (node src/index.js) y después con npm start. ¿Qué nombre aparece en cada caso?


8. Depuración básica

📘 Concepto: Depurar (debug) es encontrar y corregir errores. Llenar el código de console.log funciona, pero un depurador es mucho más potente: te permite detener el programa en una línea, ver el valor de todas las variables en ese momento y avanzar instrucción a instrucción.

8.1 Un programa con un error

// js/media.js
const notas = [7, 8.5, 6, 9];

function calcularMedia(lista) {
  let suma = 0;
  for (let i = 0; i <= lista.length; i++) { // ← aquí hay un error
    suma += lista[i];
  }
  return suma / lista.length;
}

console.log('Media:', calcularMedia(notas)); // Media: NaN  ¿Por qué?

NaN significa Not a Number: algo ha salido mal en la suma. Vamos a averiguarlo con el depurador.

8.2 Breakpoints en las DevTools

  1. Carga la página con el script y abre Sources (Chrome) o Depurador (Firefox).
  2. Busca el fichero media.js en el árbol de la izquierda (o pulsa Ctrl + P).
  3. Haz clic en el número de línea de suma += lista[i];. Aparecerá una marca azul: es un breakpoint (punto de interrupción).
  4. Recarga la página. La ejecución se detendrá en esa línea.
  5. Mira el panel Scope: verás i, suma y lista con sus valores actuales.
  6. Pulsa Resume (F8) varias veces y observa cómo cambian i y suma. Cuando i vale 4, lista[4] es undefined, y 6 + ... + undefined da NaN.

El error es la condición i <= lista.length: debería ser i < lista.length, porque los índices van de 0 a 3.

Botón / atajo (Chrome) Acción
F8 Resume Continuar hasta el siguiente breakpoint
F10 Step over Ejecutar la línea actual y pasar a la siguiente
F11 Step into Entrar dentro de la función que se llama en esta línea
Mayús + F11 Step out Terminar la función actual y volver a quien la llamó
Panel Scope Variables visibles en ese punto
Panel Watch Expresiones que quieres vigilar (por ejemplo, lista[i])
Panel Call Stack Cadena de funciones que han llevado hasta aquí

💡 Consejo: Haz clic derecho sobre el número de línea para crear un breakpoint condicional (solo se detiene si se cumple una condición, por ejemplo i === 4) o un logpoint (escribe un mensaje en la consola sin detenerse, como un console.log que no ensucia el código).

8.3 La instrucción debugger

También puedes poner un breakpoint desde el propio código:

function calcularMedia(lista) {
  let suma = 0;
  for (let i = 0; i <= lista.length; i++) {
    debugger; // el programa se detiene aquí SI las DevTools están abiertas
    suma += lista[i];
  }
  return suma / lista.length;
}

⚠️ Importante: debugger solo tiene efecto si hay un depurador conectado (por ejemplo, las DevTools abiertas). Si no, se ignora. Aun así, no lo dejes nunca en código publicado.

8.4 Depurar en Node.js y en VS Code

  • VS Code: abre la paleta (Ctrl + Mayús + P) → Debug: JavaScript Debug Terminal. Todo lo que ejecutes con node en esa terminal se conecta al depurador de VS Code y se detiene en tus breakpoints (los pones haciendo clic a la izquierda del número de línea).
  • Chrome DevTools: ejecuta node --inspect-brk src/index.js, abre chrome://inspect en Chrome y pulsa inspect. Tendrás las mismas herramientas que con una página web.

8.5 Leer un mensaje de error

Uncaught ReferenceError: nombr is not defined
    at saludar (main.js:3:15)
    at main.js:6:1
Parte Significado
Uncaught Nadie ha capturado el error (lo verás en el módulo 10)
ReferenceError El tipo de error: se usa algo que no existe
nombr is not defined La descripción: nombr no está definido (¿una errata de nombre?)
at saludar (main.js:3:15) Dónde: función saludar, fichero main.js, línea 3, columna 15
at main.js:6:1 Quién llamó a esa función (la pila de llamadas)

9. Modo estricto

9.1 ¿Qué es?

JavaScript nació siendo muy permisivo: muchos errores no producían ningún aviso y el programa seguía funcionando… mal. En ES5 (2009) se añadió el modo estricto (strict mode), una variante del lenguaje que convierte esos errores silenciosos en errores visibles y prohíbe algunas características peligrosas.

Se activa escribiendo la cadena 'use strict' (o "use strict") como primera instrucción de un fichero o de una función:

'use strict';

contador = 10; // ❌ ReferenceError: contador is not defined

Sin modo estricto, la línea anterior crea una variable global sin avisar, un error clásico cuando escribes mal el nombre de una variable.

9.2 Qué cambia

Situación Sin modo estricto Con modo estricto
Asignar a una variable no declarada Crea una variable global ReferenceError
Asignar a una propiedad de solo lectura Se ignora en silencio TypeError
Parámetros con nombre repetido function f(a, a) Permitido Error de sintaxis
this en una función normal llamada sin objeto El objeto global undefined
Números octales antiguos como 010 Valen 8 Error de sintaxis
Instrucción with Permitida Error de sintaxis
Palabras reservadas para el futuro (let, static, implements…) como nombres Algunas permitidas Error de sintaxis

9.3 Los módulos ya son estrictos

⚠️ Importante: Todo el código de un módulo ES (<script type="module">, ficheros .mjs o .js con "type": "module") y todo el cuerpo de una clase se ejecutan automáticamente en modo estricto. No necesitas escribir 'use strict'.

// prueba.mjs (módulo: estricto automáticamente)
total = 5;
console.log(total);
PS C:\cursos> node prueba.mjs
file:///C:/cursos/prueba.mjs:2
total = 5;
      ^

ReferenceError: total is not defined

Como en este curso trabajamos siempre con módulos, siempre estarás en modo estricto. Es una ventaja: el lenguaje te avisa antes de tus errores.

💡 Consejo: Si alguna vez trabajas con scripts clásicos (sin type="module") o con CommonJS, empieza cada fichero con 'use strict';.


10. Ejercicios

Ejercicio 1: Explorador de la consola

Abre la consola de las DevTools en cualquier web y:

  1. Calcula cuántos segundos tiene un año (365 * 24 * 60 * 60).
  2. Escribe document.title y comprueba que devuelve el título de la pestaña.
  3. Ejecuta document.body.style.background = 'yellow' y observa la página. Recárgala: ¿se mantiene el cambio? ¿Por qué?

Ejercicio 2: Informe en consola

Crea un fichero informe.mjs que, con los métodos de console, muestre:

  • Un grupo “Alumnos” con una tabla (console.table) de cuatro alumnos con nombre, edad y nota.
  • Una advertencia si algún alumno tiene una nota menor que 5 (puedes escribirla a mano por ahora).
  • El tiempo que tarda en ejecutarse un bucle que suma los números del 1 al 10 millones (console.time).

Ejecútalo con node --watch informe.mjs y modifica los datos para ver cómo se reejecuta.

Ejercicio 3: Las cuatro formas de cargar un script

Crea una página con cuatro scripts externos (a.js, b.js, c.js, d.js) en el <head>, cargados respectivamente de forma clásica, con defer, con async y con type="module". Cada uno debe hacer console.log de su nombre y de document.querySelector('p') (pon un párrafo en el <body>). Anota en qué orden aparecen los mensajes y cuál de ellos encuentra el párrafo. Explica el resultado con la tabla de la sección 3.4.

Ejercicio 4: Proyecto completo en el navegador

Crea el proyecto tarjeta-presentacion con la estructura de la sección 6.1. La página debe mostrar tu nombre, una frase y la fecha actual; el nombre y la fecha deben escribirse desde js/main.js (usa document.querySelector y textContent). Ábrelo con Live Server.

Ejercicio 5: Script de Node con argumentos

Crea un proyecto Node con package.json ("type": "module") y un src/index.js que reciba dos números por la línea de comandos y muestre su suma, resta, multiplicación y división. Pista: process.argv[2] es un texto; conviértelo con Number(process.argv[2]). Añade un script "calcular" al package.json y ejecútalo con npm run calcular -- 8 2.

Ejercicio 6: Caza el error con el depurador

Copia el programa de la sección 8.1 en una página, pon un breakpoint y sigue la ejecución paso a paso con F10. Añade lista[i] al panel Watch. Corrige el error y comprueba que la media es 7.625. Después repite el ejercicio en VS Code con la JavaScript Debug Terminal.

Ejercicio 7: Estricto o no estricto

Crea dos ficheros, suelto.cjs y modulo.mjs, ambos con el mismo contenido:

mensaje = 'Hola';
console.log(mensaje);

Ejecuta los dos con Node.js. ¿Qué ocurre en cada caso y por qué? Añade 'use strict'; al principio de suelto.cjs y vuelve a ejecutarlo.


Resumen

Concepto Sintaxis / herramienta
Abrir la consola F12, Ctrl + Mayús + J (Chrome/Edge), Ctrl + Mayús + K (Firefox)
Mensajes console.log(), info(), warn(), error()
Tablas y grupos console.table(), console.group() / groupEnd()
Medir tiempo console.time('x') / console.timeEnd('x')
Inspeccionar objetos console.dir(obj)
Editor VS Code + ESLint + Prettier + Live Server
Script externo <script src="js/main.js"></script>
Diferido <script src="..." defer></script>
Asíncrono <script src="..." async></script>
Módulo (recomendado) <script type="module" src="js/main.js"></script>
Comprobar Node.js node -v, npm -v
REPL node (salir con .exit)
Ejecutar un fichero node fichero.mjs
Reejecutar al guardar node --watch fichero.mjs
Proyecto Node npm init -y + npm pkg set type=module
Objeto global universal globalThis
Breakpoint en código debugger;
Modo estricto 'use strict'; (automático en módulos y clases)