Tema
Strings y template literals
Nombres, correos, mensajes, URLs, precios formateados... la mayor parte de lo que ve un usuario en pantalla es texto. En esta lección aprenderás a manipular strings con soltura: limpiarlos, buscarlos, cortarlos, darles formato y construir textos dinámicos con template literals.
Concepto
Un string es una secuencia de caracteres, como un collar de cuentas donde cada cuenta es una letra con su posición (empezando en 0).
txt
H o l a
0 1 2 3Puedes escribir strings con tres tipos de comillas:
js
const simples = 'Hola';
const dobles = "Hola";
const invertidas = `Hola`; // template literal: la más poderosaLos strings son inmutables
Ningún método modifica el string original: todos devuelven uno nuevo. nombre.toUpperCase() no cambia nombre; tienes que guardar el resultado: nombre = nombre.toUpperCase().
Template literals
Con comillas invertidas puedes interpolar variables y expresiones con ${ } y escribir en varias líneas.
js
const nombre = 'Ana';
const productos = 3;
const total = 1648.5;
// Antes (concatenación): difícil de leer
const mensaje1 = 'Hola ' + nombre + ', tienes ' + productos + ' productos por $' + total;
// Con template literal
const mensaje2 = `Hola ${nombre}, tienes ${productos} productos por $${total}`;
// Cualquier expresión vale dentro de ${}
const aviso = `Tienes ${productos} ${productos === 1 ? 'producto' : 'productos'}`;
const iva = `IVA: $${(total * 0.16).toFixed(2)}`;
// Multilínea: perfecto para generar HTML
const tarjeta = `
<article class="tarjeta">
<h2>${nombre}</h2>
<p>Productos: ${productos}</p>
</article>
`;Error común: XSS
Si metes texto que escribió el usuario dentro de un template literal y lo asignas con innerHTML, alguien podría inyectar código malicioso. Para texto del usuario usa textContent o escapa el HTML (lo verás en El DOM).
Propiedades y acceso a caracteres
js
const palabra = 'JavaScript';
palabra.length; // 10
palabra[0]; // 'J'
palabra.at(-1); // 't' (at acepta índices negativos: cuenta desde el final)
palabra.charAt(4); // 'S'Métodos esenciales
Mayúsculas, minúsculas y espacios
js
'Hola'.toUpperCase(); // 'HOLA'
'Hola'.toLowerCase(); // 'hola'
' ana@correo.com '.trim(); // 'ana@correo.com'
' hola'.trimStart(); // 'hola'
'hola '.trimEnd(); // 'hola'Buena práctica
Antes de guardar o comparar datos de un formulario, normalízalos: email.trim().toLowerCase(). Así " Ana@Correo.com" y "ana@correo.com" se consideran el mismo usuario.
Buscar
js
const frase = 'Aprender JavaScript es divertido';
frase.includes('Script'); // true
frase.startsWith('Aprender'); // true
frase.endsWith('.'); // false
frase.indexOf('es'); // 20 (posición) o -1 si no existe
frase.lastIndexOf('e'); // última apariciónExtraer partes
js
const texto = 'Desarrollo web';
texto.slice(0, 10); // 'Desarrollo' (desde 0 hasta antes del 10)
texto.slice(-3); // 'web' (los últimos 3)
texto.substring(11); // 'web'Reemplazar
js
const telefono = '33-1234-5678';
telefono.replace('-', ' '); // '33 1234-5678' (sólo el primero)
telefono.replaceAll('-', ''); // '3312345678'
telefono.replace(/-/g, ''); // igual, con expresión regularDividir, unir y repetir
js
const etiquetas = 'html,css,javascript';
etiquetas.split(','); // ['html', 'css', 'javascript']
'hola'.split(''); // ['h', 'o', 'l', 'a']
['2026', '10', '18'].join('-'); // '2026-10-18'
'ab'.repeat(3); // 'ababab'
'7'.padStart(3, '0'); // '007' (folios, horas)
'5'.padEnd(4, '.'); // '5...'Recetas útiles para proyectos reales
js
// Capitalizar: 'méxico' → 'México'
const capitalizar = (texto) =>
texto.charAt(0).toUpperCase() + texto.slice(1).toLowerCase();
// Capitalizar cada palabra: 'juan pérez' → 'Juan Pérez'
const tituloCase = (texto) =>
texto.split(' ').map(capitalizar).join(' ');
// Truncar con puntos suspensivos
const truncar = (texto, max = 50) =>
texto.length > max ? texto.slice(0, max - 1).trimEnd() + '…' : texto;
// Iniciales para avatares: 'Ana María López' → 'AL'
const iniciales = (nombre) => {
const partes = nombre.trim().split(/\s+/);
return (partes[0][0] + (partes.length > 1 ? partes.at(-1)[0] : '')).toUpperCase();
};
// Contar palabras
const contarPalabras = (texto) => texto.trim().split(/\s+/).filter(Boolean).length;
// Invertir texto
const invertir = (texto) => [...texto].reverse().join('');Slugify: textos para URLs
Un slug es la versión de un título apta para URL: "¡Hola, Ñandú Veloz!" → "hola-nandu-veloz". Se usa en blogs, tiendas y cualquier página con URLs amigables.
js
function slugify(texto) {
return texto
.toString()
.normalize('NFD') // separa letras de sus acentos: 'á' → 'a' + '´'
.replace(/[̀-ͯ]/g, '') // elimina los acentos
.toLowerCase()
.trim()
.replace(/[^a-z0-9\s-]/g, '') // quita todo lo que no sea letra, número, espacio o guion
.replace(/[\s-]+/g, '-') // espacios y guiones repetidos → un guion
.replace(/^-+|-+$/g, ''); // sin guiones al inicio o final
}
slugify('¡Hola, Ñandú Veloz!'); // 'hola-nandu-veloz'
slugify(' 10 Tips de CSS para 2026 '); // '10-tips-de-css-para-2026'Búsqueda sin acentos ni mayúsculas
js
const normalizar = (t) =>
t.normalize('NFD').replace(/[̀-ͯ]/g, '').toLowerCase();
const ciudades = ['Mérida', 'Querétaro', 'León', 'Cancún'];
const termino = 'queretaro';
ciudades.filter((c) => normalizar(c).includes(normalizar(termino)));
// ['Querétaro']Formatear números y moneda con Intl
Nunca formatees precios a mano. Intl.NumberFormat lo hace según el país, con separadores de miles y símbolo correctos.
js
const mxn = new Intl.NumberFormat('es-MX', {
style: 'currency',
currency: 'MXN'
});
mxn.format(15999); // '$15,999.00'
mxn.format(1234567.5); // '$1,234,567.50'
// Otras monedas y países
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(99.9); // '$99.90'
new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR' }).format(99.9); // '99,90 €'
// Porcentajes
new Intl.NumberFormat('es-MX', { style: 'percent' }).format(0.16); // '16 %'
// Números compactos (estadísticas, redes sociales)
new Intl.NumberFormat('es-MX', { notation: 'compact' }).format(1250000); // '1.3 M'
// Atajo rápido
(15999).toLocaleString('es-MX'); // '15,999'Buena práctica
Crea el formateador una sola vez y reutilízalo (crearlo es más costoso que usarlo):
js
// utils/formato.js
export const formatoMoneda = new Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN' });Convertir entre strings y números
js
Number('42'); // 42
Number('42abc'); // NaN
parseInt('42px'); // 42 (lee hasta donde puede)
parseFloat('3.5kg'); // 3.5
String(42); // '42'
(3.14159).toFixed(2); // '3.14' (devuelve string)Error común
Los valores de un <input> siempre son strings. '5' + 3 da '53', no 8. Convierte primero: Number(input.value) + 3, o usa input.valueAsNumber en inputs de tipo número.
Tagged templates (nivel avanzado)
Una función puede "procesar" un template literal. Así funcionan librerías como styled-components o lit-html. Por ejemplo, para escapar HTML automáticamente:
js
function escaparHTML(texto) {
return String(texto)
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
}
// strings: las partes fijas; valores: lo que va en cada ${}
function html(strings, ...valores) {
return strings.reduce(
(resultado, parte, i) => resultado + parte + (i < valores.length ? escaparHTML(valores[i]) : ''),
''
);
}
const comentario = '<img src=x onerror="alert(1)">';
const seguro = html`<p>${comentario}</p>`;
// '<p><img src=x onerror="alert(1)"></p>'Ejercicios
- Escribe
formatearTelefono('3312345678')que devuelva'(33) 1234-5678'. - Escribe
esPalindromo(texto)que ignore mayúsculas, espacios y acentos:esPalindromo('Anita lava la tina')→true. - Escribe
ocultarEmail('carlos@empresa.mx')→'c****s@empresa.mx'. - Genera un folio de pedido con el formato
'PED-000042'a partir del número42. - Usando un template literal, crea una función
resumenCarrito(items, total)que devuelva"3 productos · Total: $1,648.00"(usaIntl.NumberFormaty singular/plural).
Ver solución
js
// 1
const formatearTelefono = (tel) =>
`(${tel.slice(0, 2)}) ${tel.slice(2, 6)}-${tel.slice(6)}`;
// 2
function esPalindromo(texto) {
const limpio = texto
.normalize('NFD')
.replace(/[̀-ͯ]/g, '')
.toLowerCase()
.replace(/[^a-z0-9]/g, '');
return limpio === [...limpio].reverse().join('');
}
// 3
function ocultarEmail(email) {
const [usuario, dominio] = email.split('@');
if (usuario.length <= 2) return `${usuario[0]}*@${dominio}`;
const oculto = usuario[0] + '*'.repeat(usuario.length - 2) + usuario.at(-1);
return `${oculto}@${dominio}`;
}
// 4
const folio = (n) => `PED-${String(n).padStart(6, '0')}`;
// 5
const mxn = new Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN' });
const resumenCarrito = (items, total) =>
`${items} ${items === 1 ? 'producto' : 'productos'} · Total: ${mxn.format(total)}`;Resumen
- Los strings son inmutables: los métodos devuelven strings nuevos.
- Los template literals (
` `) permiten interpolar con${}y escribir en varias líneas. - Métodos clave:
trim,toLowerCase,includes,slice,replaceAll,split,padStart. normalize('NFD')+ regex elimina acentos: útil para slugs y búsquedas.- Formatea dinero con
Intl.NumberFormat('es-MX', { style: 'currency', currency: 'MXN' }). - Nunca metas texto del usuario en
innerHTMLsin escaparlo.
Siguiente: Fechas y Math