🎯 Objetivo del tema
El administrador aún no ha insertado un video para esta sección.
🗺️ Mapa del tema
JavaScript nació en 1995 como un lenguaje de 10 días para hacer formularios dinámicos. Hoy es el lenguaje más usado del mundo, presente en navegadores, servidores (Node.js), apps móviles (React Native), incluso en bases de datos (MongoDB). En 2015 recibió su mayor actualización: ES6, que modernizó el lenguaje. Desde entonces, cada año salen mejoras. En este tema dominarás ES6+ como base para todo lo demás.
Por qué un lenguaje 'mal diseñado' se convirtió en el más usado del mundo.
Block scope vs function scope, hoisting, y por qué var es un museo.
Sintaxis corta, this léxico, cuándo NO usarlas. Funciones puras vs arrow.
Strings con variables y la magia de extraer valores de arrays y objetos.
Las 4 operaciones que reemplazan a los bucles for en el 90% de los casos.
Cómo organizar tu código en archivos sin contaminar el scope global.
1.8.1 Historia de JavaScript: de 10 días a estándar
En mayo de 1995, Brendan Eich, ingeniero de Netscape, creó JavaScript en 10 días. Su objetivo original: validar formularios y agregar interactividad básica a las páginas. No estaba pensado para ser un lenguaje serio. La ironía: 30 años después, es el lenguaje más usado del mundo.
Lo que hoy llamamos 'JavaScript moderno' es realmente ES6+ (ES2015 en adelante). Lo que se enseña en muchos cursos viejos (con var, function(), callbacks) es JavaScript pre-2015, que ya no se usa. Si ves código con 'var' en tutoriales de 2024, huye: es código de museo.
| Concepto | Pre-ES6 (museo) | ES6+ (moderno) |
|---|---|---|
| Variable | var x = 5; | let x = 5; o const x = 5; |
| Función | function suma(a, b) { return a + b; } | const suma = (a, b) => a + b; |
| Concatenación | 'Hola ' + nombre + ' tienes ' + edad + ' años' | `Hola ${nombre}, tienes ${edad} años` |
| Asincronía | Callbacks anidados (callback hell) | async/await con promesas |
| Módulos | Un solo archivo gigante o RequireJS | import / export nativo |
El administrador aún no ha insertado un video para esta sección.
1.8.2 Variables: let, const, y el ocaso de var
Antes de ES6, solo existía var. Era problemático por su scope global y su comportamiento de hoisting. ES6 introdujo let y const, que respetan el block scope (el bloque { } donde se declaran). Regla de oro: usa const por defecto, let solo cuando necesites reasignar, NUNCA var.
// MAL: var tiene function scope, se 'escapa' de los bloques
function ejemploVar() {
if (true) {
var x = 10; // declarada dentro del if
}
console.log(x); // 10 — ¡se escapó del if!
}
// BIEN: let respeta el block scope
function ejemploLet() {
if (true) {
let x = 10; // declarada dentro del if
}
console.log(x); // ReferenceError — x no existe fuera del if
}var vs let: el problema del scope
| Palabra clave | Scope | Reasignable | Re-declarable | Cuándo usarla |
|---|---|---|---|---|
| const | Block scope (el bloque {}) | NO | NO | Por defecto. 90% de los casos. |
| let | Block scope (el bloque {}) | Sí | NO | Cuando el valor va a cambiar (contadores, acumuladores). |
| var | Function scope (la función) | Sí | Sí | NUNCA. Código legacy/museo. |
const con objetos y arrays: no es 'constante' del todo
const significa que la VARIABLE no puede reasignarse, pero el OBJETO al que apunta sí puede mutar. Es un detalle que confunde mucho al principio.
const usuario = { nombre: 'Ana', edad: 25 };
usuario.edad = 26; // ✅ válido: mutaste la propiedad
usuario = { nombre: 'Luis' }; // ❌ TypeError: no puedes reasignar la variable
const lista = [1, 2, 3];
lista.push(4); // ✅ válido: [1, 2, 3, 4]
lista = []; // ❌ TypeError: no puedes reasignar la variableconst no hace inmutable al objeto, solo a la referencia
El administrador aún no ha insertado un video para esta sección.
1.8.3 Funciones modernas: arrow functions
Las arrow functions (funciones flecha) son la forma moderna de escribir funciones. Más cortas, más legibles, y con un this léxico (que respeta el contexto donde se definen). Hay casos donde NO conviene usarlas, pero en el 80% de los casos son la mejor opción.
Las 3 formas de escribir una función
// 1. Función tradicional (museo)
function suma(a, b) {
return a + b;
}
// 2. Función tradicional como expresión (también museo)
const suma = function(a, b) {
return a + b;
};
// 3. Arrow function (moderna) — la que usarás el 90% del tiempo
const suma = (a, b) => a + b; // return implícito si es una sola expresión
// Con cuerpo de varias líneas, usas {} y return explícito
const sumaCompleta = (a, b) => {
const resultado = a + b;
console.log(`Sumando ${a} + ${b}`);
return resultado;
};Función tradicional vs arrow function
Cuándo NO usar arrow functions
- Métodos de objetos que usan 'this' (el this de arrow no es el objeto).
- Constructores de clases (las clases usan métodos normales).
- Funciones que necesitan 'arguments' (las arrow no tienen su propio arguments).
- Cuando el nombre de la función importa para el stack trace de errores.
El administrador aún no ha insertado un video para esta sección.
1.8.4 Template literals y desestructuración
Template literals y desestructuración son dos de las características más queridas de ES6. La primera elimina la concatenación fea de strings. La segunda te permite extraer valores de arrays y objetos en una sola línea.
Template literals: strings con superpoderes
// ANTES: concatenación fea y propensa a errores
const saludo = 'Hola ' + nombre + ', tienes ' + edad + ' años. ' +
'Tu ciudad es ' + ciudad + '.';
// AHORA: template literals con backticks
const saludo = `Hola ${nombre}, tienes ${edad} años. Tu ciudad es ${ciudad}.`;
// Bonus: puedes hacer expresiones dentro de ${}
const mensaje = `El doble de 5 es ${5 * 2} y la próxima edad es ${edad + 1}`;
// Bonus 2: strings multi-línea sin concatenar
const html = `
<div>
<h1>${titulo}</h1>
<p>${descripcion}</p>
</div>
`;Template literals vs concatenación
Desestructuración: extraer valores de un objeto o array
// ANTES: acceder a propiedades una por una
const usuario = { nombre: 'Ana', edad: 25, email: 'ana@mail.com' };
const nombre = usuario.nombre;
const edad = usuario.edad;
// AHORA: desestructuración en una línea
const { nombre, edad, email } = usuario;
console.log(nombre); // 'Ana'
console.log(edad); // 25
// Con arrays (por posición)
const coordenadas = [10, 20, 30];
const [x, y, z] = coordenadas;
console.log(x); // 10
// Con valores por defecto (si la propiedad no existe)
const { nombre, rol = 'invitado' } = usuario;
console.log(rol); // 'invitado' si no está definidoDesestructuración de objetos y arrays
El administrador aún no ha insertado un video para esta sección.
1.8.5 Arrays y objetos: map, filter, reduce, spread
Los 4 métodos de array más importantes de JavaScript moderno. Combinados, reemplazan al 90% de los bucles for que veías en código viejo. Cada uno hace UNA cosa y la hace bien.
| Método | Qué hace | Devuelve | Ejemplo |
|---|---|---|---|
| map() | Transforma cada elemento. | Array nuevo del mismo tamaño. | precios.map(p => p * 1.16) // con IVA |
| filter() | Filtra elementos que cumplan condición. | Array nuevo con menos (o cero) elementos. | mayores.filter(u => u.edad >= 18) |
| reduce() | Acumula todos los elementos en UN valor. | Un valor (número, objeto, string). | numeros.reduce((sum, n) => sum + n, 0) |
| spread (...) | Expande un array/objeto en otro contexto. | Copia o concatena. | [...arr1, ...arr2] // concatena |
Ejemplo completo: procesar lista de usuarios
const usuarios = [
{ nombre: 'Ana', edad: 25, activo: true },
{ nombre: 'Luis', edad: 17, activo: true },
{ nombre: 'Sofía', edad: 30, activo: false },
{ nombre: 'Pedro', edad: 19, activo: true },
];
// 1. Obtener solo los nombres de usuarios activos mayores de edad
const nombres = usuarios
.filter(u => u.activo) // solo activos
.filter(u => u.edad >= 18) // solo mayores
.map(u => u.nombre); // solo el nombre
// Resultado: ['Ana', 'Pedro']
// 2. Calcular la edad promedio
const edadPromedio = usuarios.reduce((sum, u) => sum + u.edad, 0) / usuarios.length;
// Resultado: 22.75
// 3. spread: agregar un nuevo usuario sin mutar el original
const nuevosUsuarios = [...usuarios, { nombre: 'María', edad: 28, activo: true }];filter + map + reduce + spread en acción
El administrador aún no ha insertado un video para esta sección.
1.8.6 Módulos ES6: import y export
Antes de ES6, todo el código JavaScript de una página vivía en un solo archivo (o se cargaban con tags <script> múltiples que compartían el scope global, causando caos). Los módulos ES6 resolvieron esto: cada archivo es un módulo con su propio scope, y exporta/importa lo que necesita.
La forma moderna de organizar código
// archivo: matematicas.js
export const PI = 3.14159;
export const suma = (a, b) => a + b;
export const resta = (a, b) => a - b;
// export default: solo UNO por archivo, el principal
export default class Calculadora {
static sumar(a, b) { return a + b; }
static restar(a, b) { return a - b; }
}Exportar desde matematicas.js
// archivo: app.js — usando las funciones de matematicas.js
import Calculadora, { PI, suma, resta } from './matematicas.js';
console.log(PI); // 3.14159
console.log(suma(5, 3)); // 8
console.log(resta(10, 4)); // 6
console.log(Calculadora.sumar(2, 2)); // 4Importar en app.js
| Tipo de export | Sintaxis de import | Cuándo usarlo |
|---|---|---|
| Named export (con nombre) | import { funcion } from './archivo' | Cuando hay varias cosas que importar del mismo archivo. |
| Default export (principal) | import Principal from './archivo' | Cuando hay UNA clase o función principal por archivo. |
| Import con alias | import { largo as corto } from './archivo' | Cuando el nombre choca con una variable local. |
| Import todo | import * as Mod from './archivo' | Cuando quieres agrupar todo bajo un namespace. |
El administrador aún no ha insertado un video para esta sección.
📚 Contenido ampliado
Material adicional, referencias externas verificadas y ejemplos extendidos.
🤖 AI Mission
JavaScript se aprende escribiendo, no pidiendo. Usa la IA para explicar, no para generar.
Misión: Escribe a mano una pequeña calculadora de propinas en JavaScript moderno: pide el monto de la cuenta, el porcentaje de propina, calcula el total. Después pídele a la IA que te sugiera 3 mejoras usando map/filter/reduce o desestructuración. Implementa solo las que ENTIENDAS. Anota en tu cuaderno qué aprendiste sobre this, scope, y arrow functions al escribir tu propia versión.
Pasos sugeridos
- Piensa 10 minutos: ¿qué variables necesitas? ¿qué funciones? ¿qué eventos del usuario?
- Abre VS Code y crea calculadora.js. Empieza con let/const, usa arrow functions.
- Escribe el código: pide monto, pide porcentaje, calcula, muestra resultado. Todo con prompt() y alert() para empezar.
- Refactoriza usando al menos 2 características modernas: template literals, desestructuración, o spread operator.
- Prueba con varios valores: ¿qué pasa si el usuario escribe letras? ¿si pone números negativos?
- Pídele a la IA: 'Tengo esta calculadora en JS. Sugiere 3 mejoras usando ES6+ moderno. NO me des el código completo, solo dime qué técnica aplicar y por qué.' Pega tu código.
- Aplica solo las mejoras que ENTIENDAS. Si no entiendes una, pídele a la IA que te la explique con un ejemplo AÚN más simple.
- Anota en tu cuaderno, bajo 'Lo que aprendí escribiendo': qué entendiste de this, scope, y arrow functions que la IA no te podría haber enseñado.
📓 Entregable: Tu calculadora.js con al menos 3 características ES6+, capturas de la ejecución, y media página de cuaderno reflexionando sobre qué aprendiste escribiendo código vs pidiendo código.
🚫 Errores típicos de razonamiento
Por qué: var tiene function scope y hoisting raro, lo que causa bugs sutiles. Si vienes de un tutorial viejo, lo primero que debes hacer es reemplazar TODAS las var por const (o let si necesitas reasignar). const por defecto, let solo cuando sea necesario, var NUNCA. Es la regla #1 de JavaScript moderno.
Por qué: Las arrow functions NO tienen su propio this. Si defines un método de objeto con arrow, this será undefined o el contexto exterior, no el objeto. Ejemplo del bug: const obj = { nombre: 'Ana', saludar: () => console.log(this.nombre) }; obj.saludar() muestra undefined. Solución: usa function() {} en métodos de objeto, o arrow solo cuando NO necesites this.
Por qué: Es tentador usar push/splice/sort para modificar el array original. El problema: en React, Redux y muchos frameworks, MUTAR causa bugs graves porque no detectan el cambio. La regla: prefiere crear un array nuevo ([...arr, nuevoItem] en vez de arr.push(item)). Más predecible, menos bugs.
Por qué: Si escribes const suma = (a, b) => { a + b; }, la función devuelve undefined porque no hay return explícito. A diferencia de la forma corta (=> a + b) que tiene return implícito, la forma con {} requiere return explícito. Es un error muy común que da 'NaN' o 'undefined' sin razón aparente.
Por qué: import default importa SIN llaves: import Calculadora from './math'. import nombrado usa llaves: import { suma } from './math'. Si ves 'X is not a function' al importar, es probablemente este error: mezclaste las sintaxis. Recuerda: cada archivo tiene UN export default (sin nombre al importar) y N exports nombrados (con su nombre exacto al importar).
🧪 Laboratorio práctico
Calculadora primero, framework después. Domina los fundamentos antes de las abstracciones.
Laboratorio: Lista de tareas interactiva con JavaScript moderno
Objetivo: Construir una TODO list funcional usando JavaScript ES6+ puro (sin frameworks). El usuario debe poder: agregar tareas, marcarlas como completadas, filtrarlas, y eliminarlas. Usar al menos 5 características de ES6+ (let/const, arrow functions, template literals, map/filter, módulos).
Pasos
- Crea una carpeta todo-app/ con index.html, app.js y modulo.js.
- En index.html: estructura con <input> para nueva tarea, <button> para agregar, <ul> para la lista. Enlaza <script type='module' src='app.js'>.
- En modulo.js: exporta las funciones puras: agregarTarea, toggleCompletada, filtrarActivas, eliminarTarea. Usa arrow functions, map, filter, spread.
- En app.js: importa las funciones de modulo.js, maneja los eventos del DOM (submit del form, click en checkbox, click en eliminar), actualiza la vista.
- Usa template literals para construir el HTML de cada <li> dinámicamente.
- Usa const para la lista de tareas (no let, no var).
- Guarda la lista en localStorage para que persista al recargar.
- Prueba: agregar 5 tareas, marcar 2 como hechas, filtrar solo las activas, eliminar una. Recarga la página: ¿se mantienen?
- Refactoriza: extrae toda la lógica a modulo.js, deja app.js solo con manejo de eventos.
- Abre DevTools > Console. No debe haber errores ni warnings.
- Haz commit: 'feat: TODO list con JavaScript ES6+ y módulos'.
📓 Entregable: Capturas de la TODO list funcionando, código de modulo.js con comentarios, código de app.js con eventos, y commit en Git con el mensaje final.