⚡ 1.8 · JavaScript ES6+: el lenguaje que mueve la web

⏱ 8h 00min ⚡ 120 XP 🏅 Aprendiz 📖 Fundamentos del Web FullStack
"JavaScript no se aprende memorizando: se aprende escribiendo, equivocándote y entendiendo el error."

🎯 Objetivo del tema

Al terminar este tema serás capaz de: Al terminar este tema serás capaz de escribir JavaScript moderno (ES6+) con soltura: declarar variables con let y const, escribir funciones flecha, usar template literals, desestructurar arrays y objetos, transformar colecciones con map/filter/reduce, y organizar tu código en módulos import/export. Es la base de TODO lo que viene después.
🎬
Video del instructor

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.

1. Historia de JavaScript: de 10 días a estándar

Por qué un lenguaje 'mal diseñado' se convirtió en el más usado del mundo.

2. Variables: let, const, y el ocaso de var

Block scope vs function scope, hoisting, y por qué var es un museo.

3. Funciones modernas: arrow functions

Sintaxis corta, this léxico, cuándo NO usarlas. Funciones puras vs arrow.

4. Template literals y desestructuración

Strings con variables y la magia de extraer valores de arrays y objetos.

5. Arrays y objetos: map, filter, reduce, spread

Las 4 operaciones que reemplazan a los bucles for en el 90% de los casos.

6. Módulos ES6: import y export

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.

1995
Nace JavaScript
Brendan Eich lo crea en 10 días. Originalmente se llamó Mocha, luego LiveScript, finalmente JavaScript.
1997
ECMAScript 1
Se estandariza como ECMAScript (ES) bajo el comité ECMA. Nace para evitar que Microsoft hiciera una versión incompatible (JScript).
2009
ECMAScript 5 (ES5)
Versión estable durante 10 años. strict mode, JSON nativo, array methods.
2015
ECMAScript 2015 (ES6/ES2015)
La revolución: let, const, arrow functions, clases, módulos, template literals, promesas. Cambió el lenguaje para siempre.
2016-actualidad
Actualizaciones anuales
Cada año sale una versión con mejoras: async/await (2017), optional chaining (2020), top-level await (2022).

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.

ConceptoPre-ES6 (museo)ES6+ (moderno)
Variablevar x = 5;let x = 5; o const x = 5;
Funciónfunction 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íaCallbacks anidados (callback hell)async/await con promesas
MódulosUn solo archivo gigante o RequireJSimport / export nativo
⭐ Por qué aprenderlo: JavaScript es el ÚNICO lenguaje que se ejecuta nativamente en el navegador. Todo lo demás (Python, Java, C#) necesita compilar a JavaScript. Por eso, aunque tenga quirks, no tiene rival en la web.
🎬
Video del instructor

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 claveScopeReasignableRe-declarableCuándo usarla
constBlock scope (el bloque {})NONOPor defecto. 90% de los casos.
letBlock scope (el bloque {})NOCuando el valor va a cambiar (contadores, acumuladores).
varFunction scope (la función)NUNCA. Código legacy/museo.
⭐ Regla de oro: Regla moderna: empieza SIEMPRE con const. Si el compilador/linter te dice que necesitas reasignar, cámbialo a let. NUNCA uses var. Esta disciplina te ahorra el 80% de los bugs de variables.

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 variable

const no hace inmutable al objeto, solo a la referencia

🎬
Video del instructor

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 acortar: Regla práctica: si la función hace una sola cosa y devuelve un valor, usa arrow function con return implícito. Si tiene varias líneas o efectos secundarios, usa {} con return explícito. Escribe la función MÁS CORTA que sea legible.

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.
🎬
Video del instructor

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á definido

Desestructuración de objetos y arrays

⭐ Característica estrella: La desestructuración es la característica que más código te ahorra. La verás en TODO: parámetros de funciones, hooks de React, configuración, imports. Memorízala.
🎬
Video del instructor

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étodoQué haceDevuelveEjemplo
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

⭐ Estilo moderno: Encadenar map/filter/reduce se llama 'programación funcional' y es el estilo moderno de JavaScript. Es 50% más corto, 100% más legible, y mucho más difícil de escribir bugs.
🎬
Video del instructor

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));  // 4

Importar en app.js

Tipo de exportSintaxis de importCuá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 aliasimport { largo as corto } from './archivo'Cuando el nombre choca con una variable local.
Import todoimport * as Mod from './archivo'Cuando quieres agrupar todo bajo un namespace.
⭐ No olvides el type=module: Para que import/export funcione en el navegador, agrega type='module' a tu <script>: <script type='module' src='app.js'></script>. Eso le dice al navegador 'este archivo es un módulo' y aplica las reglas de scope aislado.
🎬
Video del instructor

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

  1. Piensa 10 minutos: ¿qué variables necesitas? ¿qué funciones? ¿qué eventos del usuario?
  2. Abre VS Code y crea calculadora.js. Empieza con let/const, usa arrow functions.
  3. Escribe el código: pide monto, pide porcentaje, calcula, muestra resultado. Todo con prompt() y alert() para empezar.
  4. Refactoriza usando al menos 2 características modernas: template literals, desestructuración, o spread operator.
  5. Prueba con varios valores: ¿qué pasa si el usuario escribe letras? ¿si pone números negativos?
  6. 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.
  7. 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.
  8. 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

Error 1: Usar var en código nuevo.
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.
Error 2: Usar arrow functions en métodos de objeto y romper el 'this'.
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.
Error 3: Mutar arrays/objetos cuando podrías crear uno nuevo con map/filter/spread.
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.
Error 4: Olvidar el return en arrow functions con cuerpo de varias líneas.
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.
Error 5: Confundir import default con import nombrado.
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

  1. Crea una carpeta todo-app/ con index.html, app.js y modulo.js.
  2. En index.html: estructura con <input> para nueva tarea, <button> para agregar, <ul> para la lista. Enlaza <script type='module' src='app.js'>.
  3. En modulo.js: exporta las funciones puras: agregarTarea, toggleCompletada, filtrarActivas, eliminarTarea. Usa arrow functions, map, filter, spread.
  4. 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.
  5. Usa template literals para construir el HTML de cada <li> dinámicamente.
  6. Usa const para la lista de tareas (no let, no var).
  7. Guarda la lista en localStorage para que persista al recargar.
  8. Prueba: agregar 5 tareas, marcar 2 como hechas, filtrar solo las activas, eliminar una. Recarga la página: ¿se mantienen?
  9. Refactoriza: extrae toda la lógica a modulo.js, deja app.js solo con manejo de eventos.
  10. Abre DevTools > Console. No debe haber errores ni warnings.
  11. 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.

📓 Tu cuaderno: Anota pseudocódigo, diagramas, errores que encontraste y respuestas a "explica sin código". La escritura manual refuerza tu razonamiento. Tu profesor puede pedirte que subas fotos de páginas específicas.