← Blog
2 min de lecturaES

Guía esencial de ES6: Las features que transformaron JavaScript

Descubre las características más importantes de ECMAScript 2015 (ES6) que revolucionaron JavaScript: arrow functions, destructuring, template literals, promesas, módulos y mucho más.

Tabla de contenidos

ES6 (ECMAScript 2015) fue la mayor actualización de JavaScript en su historia. Introdujo una sintaxis más moderna, patrones más limpios y herramientas que hoy usamos a diario. En este artículo repasamos las features más importantes con ejemplos prácticos.


let y const — Adiós al var

Antes de ES6, solo teníamos var para declarar variables. El problema era que var tiene scope de función, no de bloque, lo que causaba bugs inesperados.

// ❌ var — scope de función, se puede redeclarar var nombre = "Ana"; var nombre = "Luis"; // No da error // ✅ let — scope de bloque, reasignable let edad = 25; edad = 26; // OK // ✅ const — scope de bloque, no reasignable const PI = 3.14159; // PI = 3; // ❌ TypeError: Assignment to constant variable

Diferencias clave

Característica var let const
Scope Función Bloque Bloque
Redeclarable No No
Reasignable No
Hoisting Sí (inicializado como undefined) Sí (temporal dead zone) Sí (temporal dead zone)

Regla general: Usa const por defecto. Usa let solo cuando necesites reasignar. Nunca uses var.


Arrow Functions

Las arrow functions son una forma más concisa de escribir funciones. Además, no crean su propio this, lo que resuelve muchos problemas clásicos con callbacks.

// Función tradicional function sumar(a, b) { return a + b; } // Arrow function const sumar = (a, b) => a + b; // Con un solo parámetro, los paréntesis son opcionales const doble = x => x * 2; // Con cuerpo de múltiples líneas const calcular = (a, b) => { const resultado = a * b; return resultado + 10; };

El problema del this resuelto

// ❌ Antes de ES6 — this se pierde en callbacks function Contador() { this.count = 0; setInterval(function () { this.count++; // 'this' NO es el Contador, es window/undefined }, 1000); } // ✅ Con arrow function — this se hereda del scope padre function Contador() { this.count = 0; setInterval(() => { this.count++; // 'this' SÍ es el Contador }, 1000); }

Template Literals

Los template literals permiten crear strings con interpolación de variables y multilínea usando backticks.

const nombre = "Carlos"; const edad = 30; // ❌ Concatenación clásica const saludo = "Hola, me llamo " + nombre + " y tengo " + edad + " años."; // ✅ Template literal const saludo = `Hola, me llamo ${nombre} y tengo ${edad} años.`; // Multilínea const html = ` <div class="card"> <h2>${nombre}</h2> <p>Edad: ${edad}</p> </div> `; // Expresiones dentro de ${} const mensaje = `En 5 años tendré ${edad + 5} años.`;

Destructuring

El destructuring permite extraer valores de arrays y objetos en variables individuales de forma directa.

Destructuring de objetos

const usuario = { nombre: "María", edad: 28, ciudad: "Madrid", trabajo: "Desarrolladora" }; // ❌ Sin destructuring const nombre = usuario.nombre; const edad = usuario.edad; // ✅ Con destructuring const { nombre, edad, ciudad } = usuario; // Renombrar variables const { nombre: userName, edad: userAge } = usuario; // Valores por defecto const { nombre, pais = "España" } = usuario; // Destructuring anidado const empresa = { datos: { nombre: "TechCorp", direccion: { ciudad: "Barcelona", cp: "08001" } } }; const { datos: { direccion: { ciudad } } } = empresa;

Destructuring de arrays

const colores = ["rojo", "verde", "azul", "amarillo"]; // Extraer elementos const [primero, segundo] = colores; // primero → "rojo", segundo → "verde" // Saltar elementos const [, , tercero] = colores; // tercero → "azul" // Rest operator const [cabeza, ...resto] = colores; // cabeza → "rojo", resto → ["verde", "azul", "amarillo"] // Intercambiar variables let a = 1, b = 2; [a, b] = [b, a]; // a → 2, b → 1

Spread y Rest Operators (...)

Los tres puntos (...) sirven para dos cosas: spread (expandir) y rest (recoger).

// SPREAD — expandir arrays/objetos const nums = [1, 2, 3]; const masNums = [...nums, 4, 5]; // [1, 2, 3, 4, 5] // Copiar un array (shallow copy) const copia = [...nums]; // Merge de objetos const base = { color: "azul", tamaño: "M" }; const extra = { tamaño: "L", peso: "200g" }; const merged = { ...base, ...extra }; // { color: "azul", tamaño: "L", peso: "200g" } // REST — recoger argumentos function sumarTodos(...numeros) { return numeros.reduce((acc, n) => acc + n, 0); } sumarTodos(1, 2, 3, 4); // 10

Promesas y Async/Await

Las promesas son el mecanismo estándar para manejar operaciones asíncronas en JavaScript.

Promesas

// Crear una promesa const obtenerDatos = () => { return new Promise((resolve, reject) => { setTimeout(() => { const datos = { id: 1, nombre: "Producto" }; resolve(datos); // reject(new Error("Fallo al obtener datos")); }, 1000); }); }; // Consumir la promesa obtenerDatos() .then(datos => console.log(datos)) .catch(error => console.error(error)) .finally(() => console.log("Operación completada"));

Async/Await (ES2017, pero complementa las promesas de ES6)

// Async/await hace que el código asíncrono parezca síncrono async function cargarUsuario(id) { try { const response = await fetch(`/api/usuarios/${id}`); const usuario = await response.json(); return usuario; } catch (error) { console.error("Error cargando usuario:", error); } } // Ejecutar varias promesas en paralelo async function cargarTodo() { const [usuarios, productos] = await Promise.all([ fetch("/api/usuarios").then(r => r.json()), fetch("/api/productos").then(r => r.json()) ]); console.log(usuarios, productos); }

Módulos (import / export)

ES6 introdujo un sistema de módulos nativo para JavaScript, permitiendo organizar el código en archivos separados.

// 📁 utils/math.js export const PI = 3.14159; export function sumar(a, b) { return a + b; } export default function multiplicar(a, b) { return a * b; } // 📁 app.js import multiplicar, { PI, sumar } from "./utils/math.js"; console.log(sumar(2, 3)); // 5 console.log(multiplicar(4, 5)); // 20 console.log(PI); // 3.14159

Tipos de export/import

// Named exports — puedes tener varios por archivo export const nombre = "valor"; export function fn() {} // Default export — solo uno por archivo export default function principal() {} // Import con alias import { sumar as add } from "./math.js"; // Import todo el módulo import * as MathUtils from "./math.js"; MathUtils.sumar(1, 2);

Clases

ES6 introdujo la sintaxis class como azúcar sintáctico sobre el sistema de prototipos de JavaScript.

class Animal { constructor(nombre, sonido) { this.nombre = nombre; this.sonido = sonido; } hablar() { return `${this.nombre} hace ${this.sonido}`; } // Getter get info() { return `${this.nombre} (${this.sonido})`; } // Método estático static crearPerro() { return new Animal("Perro", "Guau"); } } // Herencia class Gato extends Animal { constructor(nombre, color) { super(nombre, "Miau"); this.color = color; } hablar() { return `${super.hablar()} 🐱`; } } const michi = new Gato("Luna", "negro"); michi.hablar(); // "Luna hace Miau 🐱"

Otras features importantes

Map y Set

// Map — diccionario con claves de cualquier tipo const mapa = new Map(); mapa.set("nombre", "Ana"); mapa.set(42, "la respuesta"); mapa.set(true, "booleano como clave"); mapa.get("nombre"); // "Ana" mapa.size; // 3 // Set — colección de valores únicos const unicos = new Set([1, 2, 2, 3, 3, 3]); // Set {1, 2, 3} unicos.add(4); unicos.has(2); // true unicos.delete(1);

Símbolos

// Symbol — identificador único e inmutable const id = Symbol("id"); const usuario = { [id]: 123, nombre: "Pedro" }; usuario[id]; // 123 // El símbolo no aparece en for...in ni Object.keys()

Valores por defecto en parámetros

function crearUsuario(nombre, rol = "usuario", activo = true) { return { nombre, rol, activo }; } crearUsuario("Ana"); // { nombre: "Ana", rol: "usuario", activo: true } crearUsuario("Luis", "admin"); // { nombre: "Luis", rol: "admin", activo: true }

Shorthand en objetos

const nombre = "Sara"; const edad = 25; // ❌ Antes const persona = { nombre: nombre, edad: edad }; // ✅ ES6 shorthand const persona = { nombre, edad }; // Métodos shorthand const calc = { sumar(a, b) { return a + b; }, restar(a, b) { return a - b; } };

Conclusión

ES6 transformó JavaScript de un lenguaje con muchas limitaciones a uno moderno y expresivo. Estas features no son solo azúcar sintáctico — cambian la forma en la que estructuramos, organizamos y pensamos nuestro código.

Si aún no estás usando todas estas características, el mejor momento para empezar es ahora. La mayoría de navegadores modernos y Node.js las soportan nativamente, así que no hay excusas.

¡Happy coding!