JavaScript

JavaScript

Tutorial JavaScript: Métodos de Strings

JavaScript strings: aprende las propiedades y métodos básicos para manipular texto con eficacia. Fundamentales para mejorar tus proyectos de programación.

Aprende JavaScript y certifícate

Propiedades y métodos básicos

Los strings en JavaScript son secuencias de caracteres que representan texto. A diferencia de otros lenguajes, JavaScript no tiene un tipo específico para caracteres individuales; un carácter es simplemente un string de longitud 1. Vamos a explorar las propiedades y métodos fundamentales que nos permiten trabajar con strings de manera efectiva.

Propiedad length

La propiedad más básica y utilizada de un string es length, que nos devuelve el número de caracteres que contiene:

const greeting = "Hello, world!";
console.log(greeting.length); // 13

Esta propiedad es inmutable y de solo lectura, lo que significa que no podemos modificarla directamente:

const text = "JavaScript";
text.length = 4; // Esto no tiene efecto
console.log(text.length); // Sigue siendo 10

Acceso a caracteres individuales

Existen dos formas principales de acceder a caracteres individuales dentro de un string:

  • Notación de corchetes:
const language = "JavaScript";
console.log(language[0]); // "J"
console.log(language[4]); // "S"
  • Método charAt():
const language = "JavaScript";
console.log(language.charAt(0)); // "J"
console.log(language.charAt(4)); // "S"

La diferencia principal es que charAt() devuelve un string vacío cuando se accede a un índice fuera de rango, mientras que la notación de corchetes devuelve undefined:

const word = "Code";
console.log(word[10]); // undefined
console.log(word.charAt(10)); // "" (string vacío)

Búsqueda en strings

JavaScript ofrece varios métodos para localizar substrings o caracteres dentro de un string:

  • indexOf()

Devuelve la primera posición donde aparece el substring especificado, o -1 si no se encuentra:

const sentence = "JavaScript is amazing";
console.log(sentence.indexOf("Script")); // 4
console.log(sentence.indexOf("Java")); // 0
console.log(sentence.indexOf("PHP")); // -1

También acepta un segundo parámetro opcional que indica desde qué posición comenzar la búsqueda:

const text = "The rain in Spain stays mainly in the plain";
console.log(text.indexOf("in")); // 5
console.log(text.indexOf("in", 6)); // 12
  • lastIndexOf()

Similar a indexOf(), pero busca desde el final hacia el principio, devolviendo la última ocurrencia:

const phrase = "The quick brown fox jumps over the lazy dog";
console.log(phrase.lastIndexOf("the")); // 31
console.log(phrase.lastIndexOf("fox")); // 16
  • includes()

Método más moderno que simplemente verifica si un string contiene otro, devolviendo un booleano:

const message = "Welcome to JavaScript course";
console.log(message.includes("JavaScript")); // true
console.log(message.includes("Python")); // false

También acepta una posición desde donde comenzar la búsqueda:

const text = "Hello world";
console.log(text.includes("o", 5)); // true
console.log(text.includes("o", 8)); // false
  • startsWith() y endsWith()

Estos métodos verifican si un string comienza o termina con el substring especificado:

const filename = "document.pdf";
console.log(filename.startsWith("doc")); // true
console.log(filename.endsWith(".pdf")); // true
console.log(filename.endsWith("txt")); // false

Ambos métodos también aceptan un parámetro opcional para indicar la posición:

const url = "https://example.com/path";
console.log(url.startsWith("example", 8)); // true

const file = "report-2023.xlsx";
console.log(file.endsWith("report", 6)); // true

Extracción de substrings

JavaScript proporciona tres métodos principales para extraer partes de un string:

  • slice()

Extrae una sección del string y devuelve un nuevo string sin modificar el original:

const text = "The morning is upon us";
console.log(text.slice(4, 11)); // "morning"
console.log(text.slice(12)); // "is upon us"

slice() también acepta índices negativos, que cuentan desde el final del string:

const word = "JavaScript";
console.log(word.slice(-6)); // "Script"
console.log(word.slice(4, -1)); // "Scrip"
  • substring()

Similar a slice(), pero con algunas diferencias clave:

const str = "Mozilla";
console.log(str.substring(1, 3)); // "oz"
console.log(str.substring(2)); // "zilla"

A diferencia de slice(), substring() trata los valores negativos como 0 y automáticamente intercambia los argumentos si el primero es mayor que el segundo:

const text = "JavaScript";
console.log(text.substring(4, 0)); // "Java" (intercambia 4 y 0)
console.log(text.substring(-3)); // "JavaScript" (trata -3 como 0)
  • substr() (Considerado obsoleto)

Aunque sigue funcionando, este método está desaconsejado en favor de slice() y substring(). Extrae caracteres desde una posición y con una longitud determinada:

const language = "JavaScript";
console.log(language.substr(4, 6)); // "Script"

Métodos de comparación

  • charCodeAt()

Devuelve el valor Unicode del carácter en la posición especificada:

const text = "ABC";
console.log(text.charCodeAt(0)); // 65 (código Unicode para 'A')
console.log(text.charCodeAt(1)); // 66 (código Unicode para 'B')
  • codePointAt()

Similar a charCodeAt(), pero con mejor soporte para caracteres que ocupan más de 16 bits (como emojis):

const emoji = "😀";
console.log(emoji.codePointAt(0)); // 128512
  • localeCompare()

Compara dos strings en el orden alfabético según la configuración regional:

const a = "apple";
const b = "banana";

console.log(a.localeCompare(b)); // -1 (a viene antes que b)
console.log(b.localeCompare(a)); // 1 (b viene después que a)
console.log(a.localeCompare(a)); // 0 (son iguales)

Este método es especialmente útil para ordenar strings que contienen caracteres específicos de un idioma:

const words = ["café", "cafetería", "cafe"];
words.sort((a, b) => a.localeCompare(b, "es"));
console.log(words); // ["cafe", "café", "cafetería"]

Concatenación de strings

Existen varias formas de combinar strings en JavaScript:

  • Operador +
const firstName = "John";
const lastName = "Doe";
const fullName = firstName + " " + lastName;
console.log(fullName); // "John Doe"
  • Método concat()
const greeting = "Hello";
const name = "World";
console.log(greeting.concat(", ", name, "!")); // "Hello, World!"
  • Template literals (ES6+)

La forma más moderna y legible de concatenar strings:

const product = "Laptop";
const price = 999;
const currency = "USD";

const message = `The ${product} costs ${price} ${currency}`;
console.log(message); // "The Laptop costs 999 USD"

Repetición de strings

El método repeat() permite crear un nuevo string que contiene copias del original:

const star = "*";
console.log(star.repeat(5)); // "*****"

const hello = "Hello ";
console.log(hello.repeat(3)); // "Hello Hello Hello "

Este método es útil para crear patrones o indentación:

function createIndent(level) {
    return "  ".repeat(level);
}

console.log(createIndent(3) + "- Item"); // "      - Item"

Eliminación de espacios en blanco

JavaScript ofrece métodos para eliminar espacios en blanco al principio y/o final de un string:

  • trim()

Elimina espacios en blanco de ambos extremos:

const text = "   Hello world!   ";
console.log(text.trim()); // "Hello world!"
  • trimStart() / trimLeft()

Elimina espacios en blanco solo del inicio:

const input = "   user@example.com";
console.log(input.trimStart()); // "user@example.com"
  • trimEnd() / trimRight()

Elimina espacios en blanco solo del final:

const code = "ABC123   ";
console.log(code.trimEnd()); // "ABC123"

Estos métodos son particularmente útiles al procesar entradas de usuario o datos de formularios:

function validateEmail(email) {
    const trimmedEmail = email.trim();
    return trimmedEmail.includes("@") && trimmedEmail.includes(".");
}

console.log(validateEmail("  user@example.com  ")); // true

Los métodos básicos de strings en JavaScript proporcionan una base sólida para manipular texto de manera efectiva. Dominar estas herramientas fundamentales es esencial antes de avanzar hacia técnicas más avanzadas de transformación y manipulación de strings.

Transformación de strings

JavaScript ofrece un conjunto robusto de métodos para transformar strings, permitiéndonos modificar el texto de diversas maneras sin alterar el string original. Estas transformaciones son fundamentales en el desarrollo web moderno, desde la manipulación de datos de usuario hasta el formateo de texto para presentación.

Cambios de mayúsculas y minúsculas

Los métodos de cambio de caso son probablemente las transformaciones más comunes que realizamos en strings:

  • toUpperCase()

Convierte todos los caracteres a mayúsculas:

const message = "Hello, World!";
console.log(message.toUpperCase()); // "HELLO, WORLD!"
  • toLowerCase()

Convierte todos los caracteres a minúsculas:

const username = "JohnDoe123";
console.log(username.toLowerCase()); // "johndoe123"

Estos métodos son particularmente útiles para normalizar entradas de usuario o realizar comparaciones insensibles a mayúsculas/minúsculas:

function checkPassword(input, storedPassword) {
    // Comparación insensible a mayúsculas/minúsculas
    return input.toLowerCase() === storedPassword.toLowerCase();
}
  • toLocaleLowerCase() y toLocaleUpperCase()

Versiones que respetan las reglas de conversión específicas del idioma:

const turkishText = "İstanbul";
console.log(turkishText.toLowerCase()); // "i̇stanbul"
console.log(turkishText.toLocaleLowerCase('tr')); // "istanbul"

Estos métodos son cruciales cuando se trabaja con idiomas que tienen reglas especiales de conversión de caso.

Reemplazo de texto

JavaScript proporciona métodos potentes para sustituir partes de un string por otro contenido:

  • replace()

Reemplaza la primera ocurrencia de un patrón (string o expresión regular) con otro string:

const text = "The quick brown fox";
console.log(text.replace("quick", "fast")); // "The fast brown fox"

Con expresiones regulares, podemos hacer reemplazos más sofisticados:

const html = "<div>Hello</div>";
const plainText = html.replace(/<[^>]*>/g, "");
console.log(plainText); // "Hello"

El flag g (global) permite reemplazar todas las ocurrencias, no solo la primera:

const sentence = "apple orange apple banana apple";
console.log(sentence.replace(/apple/g, "pear")); // "pear orange pear banana pear"
  • replaceAll() (ES2021+)

Método moderno que reemplaza todas las ocurrencias sin necesidad de expresiones regulares:

const phrase = "The car is red and the bike is red too";
console.log(phrase.replaceAll("red", "blue")); // "The car is blue and the bike is blue too"

También acepta expresiones regulares con el flag global:

const code = "function add(x, y) { return x + y; }";
console.log(code.replaceAll(/[xy]/g, "param")); // "function add(param, param) { return param + param; }"

Uso de funciones de reemplazo

Tanto replace() como replaceAll() pueden utilizar una función para determinar el valor de reemplazo:

const prices = "Product A: $10, Product B: $25, Product C: $15";

// Aumentar todos los precios en un 10%
const updatedPrices = prices.replace(/\$(\d+)/g, (match, price) => {
    const newPrice = Math.round(parseInt(price) * 1.1);
    return `$${newPrice}`;
});

console.log(updatedPrices); // "Product A: $11, Product B: $28, Product C: $17"

Esta técnica es extremadamente poderosa para transformaciones complejas basadas en el contenido encontrado.

Relleno y alineación

JavaScript ofrece métodos para ajustar la longitud de un string añadiendo caracteres al principio o al final:

  • padStart()

Rellena el string desde el principio hasta alcanzar la longitud deseada:

const number = "42";
console.log(number.padStart(5, "0")); // "00042"

const reference = "ABC";
console.log(reference.padStart(10, "-")); // "-------ABC"

Este método es ideal para formatear números, códigos de referencia o crear alineaciones en texto:

// Formatear números de tarjeta de crédito
const lastFourDigits = "1234";
const maskedCardNumber = lastFourDigits.padStart(16, "*");
console.log(maskedCardNumber); // "************1234"
  • padEnd()

Similar a padStart(), pero añade el relleno al final del string:

const productCode = "XYZ";
console.log(productCode.padEnd(10, ".")); // "XYZ......."

const name = "Report";
console.log(name.padEnd(20, " ") + "| Status: Complete"); // "Report              | Status: Complete"

Estos métodos son particularmente útiles para crear tablas de texto alineadas o formatear datos para presentación:

function createTable(data) {
    return data.map(item => {
        return item.name.padEnd(15, " ") + 
               item.category.padEnd(10, " ") + 
               item.price.toString().padStart(8, " ");
    }).join("\n");
}

const products = [
    { name: "Laptop", category: "Tech", price: 1299 },
    { name: "Headphones", category: "Audio", price: 199 },
    { name: "Mouse", category: "Tech", price: 25 }
];

console.log(createTable(products));
// Laptop         Tech      1299
// Headphones     Audio      199
// Mouse          Tech        25

Normalización de strings

La normalización es crucial cuando se trabaja con caracteres Unicode, especialmente para comparaciones o búsquedas:

const char1 = "\u00F1"; // ñ como un solo carácter
const char2 = "\u006E\u0303"; // ñ como 'n' + tilde combinante

console.log(char1 === char2); // false
console.log(char1.normalize() === char2.normalize()); // true

El método normalize() acepta diferentes formas de normalización:

const text = "café";

// Diferentes formas de normalización
console.log(text.normalize("NFC")); // Forma de composición canónica
console.log(text.normalize("NFD")); // Forma de descomposición canónica
console.log(text.normalize("NFKC")); // Forma de composición de compatibilidad
console.log(text.normalize("NFKD")); // Forma de descomposición de compatibilidad

La normalización es especialmente importante cuando se procesan textos internacionales o se realizan operaciones de ordenación y búsqueda.

Conversión entre strings y arrays

La transformación entre strings y arrays es una operación frecuente en JavaScript:

  • split()

Divide un string en un array de substrings basándose en un separador:

const sentence = "The quick brown fox jumps over the lazy dog";
const words = sentence.split(" ");
console.log(words); // ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]

const csvData = "John,Doe,35,Developer";
const fields = csvData.split(",");
console.log(fields); // ["John", "Doe", "35", "Developer"]

Podemos limitar el número de elementos resultantes con un segundo parámetro:

const text = "a:b:c:d:e:f";
console.log(text.split(":", 3)); // ["a", "b", "c"]

También podemos usar expresiones regulares como separador:

const input = "Hello  World\tJavaScript\nProgramming";
const parts = input.split(/\s+/); // Divide por cualquier espacio en blanco
console.log(parts); // ["Hello", "World", "JavaScript", "Programming"]
  • Array.join()

El complemento de split() es el método join() de los arrays, que une elementos en un string:

const fruits = ["Apple", "Banana", "Cherry"];
console.log(fruits.join(", ")); // "Apple, Banana, Cherry"

const path = ["users", "john", "documents", "report.pdf"];
console.log(path.join("/")); // "users/john/documents/report.pdf"

Estas transformaciones son fundamentales para procesar datos estructurados:

// Convertir una frase a slug para URL
function slugify(text) {
    return text
        .toLowerCase()
        .split(" ")
        .filter(word => word.length > 0)
        .join("-");
}

console.log(slugify("JavaScript String Methods")); // "javascript-string-methods"

Transformación con template literals

Los template literals (ES6+) ofrecen una forma elegante de transformar strings mediante interpolación:

const user = {
    name: "Alice",
    age: 28,
    role: "Developer"
};

const greeting = `Hello, ${user.name}! You are ${user.age} years old and work as a ${user.role}.`;
console.log(greeting); // "Hello, Alice! You are 28 years old and work as a Developer."

Podemos incluir expresiones JavaScript completas dentro de la interpolación:

const price = 19.99;
const tax = 0.21;

const receipt = `
Product: Premium Subscription
Price: $${price.toFixed(2)}
Tax (21%): $${(price * tax).toFixed(2)}
Total: $${(price + price * tax).toFixed(2)}
`;

console.log(receipt);
// Product: Premium Subscription
// Price: $19.99
// Tax (21%): $4.20
// Total: $24.19
  • Tagged templates

Una característica avanzada son las plantillas etiquetadas, que permiten procesar template literals con una función:

function highlight(strings, ...values) {
    return strings.reduce((result, str, i) => {
        const value = values[i] || '';
        return result + str + (value ? `<strong>${value}</strong>` : '');
    }, '');
}

const name = "JavaScript";
const year = 1995;
const message = highlight`The language ${name} was created in ${year}.`;

console.log(message); // "The language <strong>JavaScript</strong> was created in <strong>1995</strong>."

Esta técnica es la base de bibliotecas populares como styled-components para React.

Transformación de caracteres individuales

Para transformaciones a nivel de carácter, podemos combinar varios métodos:

// Capitalizar la primera letra de cada palabra
function titleCase(text) {
    return text
        .toLowerCase()
        .split(' ')
        .map(word => word.charAt(0).toUpperCase() + word.slice(1))
        .join(' ');
}

console.log(titleCase("the quick brown fox")); // "The Quick Brown Fox"

Otro ejemplo es la conversión de camelCase a kebab-case:

function camelToKebab(text) {
    return text.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
}

console.log(camelToKebab("backgroundColor")); // "background-color"
console.log(camelToKebab("userProfileSettings")); // "user-profile-settings"

Transformación con expresiones regulares

Las expresiones regulares amplían enormemente nuestras capacidades de transformación:

// Extraer todos los números de un texto
function extractNumbers(text) {
    const matches = text.match(/\d+/g) || [];
    return matches.map(Number);
}

console.log(extractNumbers("The price is $42.99 for 3 items")); // [42, 99, 3]

Podemos usar replace() con captura de grupos para reorganizar texto:

// Invertir el formato de fecha de DD/MM/YYYY a YYYY-MM-DD
function reformatDate(dateStr) {
    return dateStr.replace(/(\d{2})\/(\d{2})\/(\d{4})/, '$3-$2-$1');
}

console.log(reformatDate("25/12/2023")); // "2023-12-25"

Las expresiones regulares también son útiles para eliminar o reemplazar patrones complejos:

// Eliminar etiquetas HTML manteniendo su contenido
function stripHtml(html) {
    return html.replace(/<[^>]*>|<\/[^>]*>/g, '');
}

console.log(stripHtml("<p>Hello <strong>World</strong>!</p>")); // "Hello World!"

La combinación de métodos de string con expresiones regulares proporciona herramientas poderosas para casi cualquier transformación de texto que necesitemos realizar en nuestras aplicaciones JavaScript.

Manipulación avanzada

La manipulación avanzada de strings en JavaScript va más allá de las operaciones básicas, permitiéndonos resolver problemas complejos de procesamiento de texto con elegancia y eficiencia. Estas técnicas son esenciales para desarrolladores que necesitan implementar funcionalidades sofisticadas como validación de formatos, análisis de texto o transformaciones complejas.

Expresiones regulares avanzadas

Las expresiones regulares son una herramienta poderosa para manipulación de texto, especialmente cuando necesitamos patrones complejos:

  • Lookaheads y lookbehinds

Estas construcciones permiten crear condiciones sin consumir caracteres:

// Contraseña que contenga al menos una letra mayúscula, una minúscula y un número
const strongPassword = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d).{8,}$/;

console.log(strongPassword.test("Abc12345")); // true
console.log(strongPassword.test("abcdefgh")); // false (sin mayúsculas ni números)

Los lookbehinds (disponibles en navegadores modernos) permiten verificar lo que precede a un patrón:

// Capturar números que estén precedidos por un símbolo $
const priceRegex = /(?<=\$)\d+(\.\d{2})?/g;
const text = "Products: $25.99, €30.50, $15";
console.log(text.match(priceRegex)); // ["25.99", "15"]
  • Grupos de captura nombrados

Facilitan el trabajo con partes específicas del patrón:

const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = "2023-11-15".match(dateRegex);

console.log(match.groups.year);  // "2023"
console.log(match.groups.month); // "11"
console.log(match.groups.day);   // "15"

Esto es particularmente útil para extraer información estructurada:

function parseURL(url) {
    const regex = /^(?<protocol>https?):\/\/(?<domain>[^\/]+)(?<path>\/.*)?$/;
    const match = url.match(regex);
    
    return match ? match.groups : null;
}

const urlInfo = parseURL("https://developer.mozilla.org/en-US/docs/Web/JavaScript");
console.log(urlInfo);
// { protocol: "https", domain: "developer.mozilla.org", path: "/en-US/docs/Web/JavaScript" }
  • Expresiones regulares con flags avanzados

JavaScript soporta varios flags que modifican el comportamiento de las expresiones regulares:

// Flag 's' (dotAll) - permite que el punto coincida con saltos de línea
const multilineText = `First line
Second line`;

console.log(/First.*Second/s.test(multilineText)); // true
console.log(/First.*Second/.test(multilineText));  // false (sin flag 's')

// Flag 'y' (sticky) - busca solo desde la posición lastIndex
const regex = /\d+/y;
const text = "price: 23, quantity: 5";
regex.lastIndex = 7; // Comenzar búsqueda desde la posición 7
console.log(regex.exec(text)[0]); // "23"

Procesamiento de texto Unicode

JavaScript moderno ofrece soporte mejorado para caracteres Unicode, esencial para aplicaciones internacionales:

  • Puntos de código y caracteres compuestos
// Obtener el punto de código de un emoji
const emoji = "🚀";
console.log(emoji.codePointAt(0).toString(16)); // "1f680"

// Crear un carácter desde un punto de código
console.log(String.fromCodePoint(0x1f680)); // "🚀"
  • Iteración correcta sobre caracteres Unicode

Los emojis y otros caracteres pueden ocupar múltiples posiciones en un string JavaScript:

const text = "😊👨‍👩‍👧‍👦🇪🇸";

// Método incorrecto (divide caracteres compuestos)
for (let i = 0; i < text.length; i++) {
    console.log(text[i]);
}

// Método correcto usando for...of
for (const char of text) {
    console.log(char);
}

// Convertir a array de caracteres Unicode correctamente
console.log([...text]); // ["😊", "👨‍👩‍👧‍👦", "🇪🇸"]
console.log(text.length); // 13 (cuenta unidades de código, no caracteres visibles)
console.log([...text].length); // 3 (cuenta caracteres visibles correctamente)
  • Normalización para comparaciones
// Comparación de strings con caracteres acentuados
function normalizedCompare(str1, str2) {
    return str1.normalize() === str2.normalize();
}

const a = "café"; // 'é' como un solo carácter
const b = "cafe\u0301"; // 'e' seguido del acento combinante

console.log(a === b); // false
console.log(normalizedCompare(a, b)); // true

Manipulación basada en contexto

A veces necesitamos transformar texto basándonos en su contexto o posición:

  • Reemplazo condicional
// Censurar palabras inapropiadas pero preservar la primera letra
function censorText(text, badWords) {
    return text.replace(new RegExp(`\\b(${badWords.join('|')})\\b`, 'gi'), match => {
        return match[0] + '*'.repeat(match.length - 1);
    });
}

const message = "That stupid idea is damn ridiculous!";
console.log(censorText(message, ["stupid", "damn"])); // "That s***** idea is d*** ridiculous!"
  • Transformación basada en posición
// Convertir snake_case a camelCase
function snakeToCamel(text) {
    return text.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
}

console.log(snakeToCamel("user_first_name")); // "userFirstName"
  • Manipulación con funciones de orden superior
// Aplicar diferentes transformaciones a partes específicas de un texto
function transformParts(text, pattern, transformer) {
    const parts = [];
    let lastIndex = 0;
    let match;
    
    const regex = new RegExp(pattern, 'g');
    while ((match = regex.exec(text)) !== null) {
        // Añadir texto sin cambios antes del match
        parts.push(text.slice(lastIndex, match.index));
        // Añadir texto transformado
        parts.push(transformer(match[0]));
        lastIndex = match.index + match[0].length;
    }
    
    // Añadir el resto del texto
    parts.push(text.slice(lastIndex));
    
    return parts.join('');
}

// Ejemplo: Convertir fechas de formato MM/DD/YYYY a DD-MM-YYYY
const text = "Meeting scheduled for 11/15/2023 and follow-up on 12/01/2023";
const result = transformParts(
    text,
    '\\d{2}/\\d{2}/\\d{4}',
    date => {
        const [month, day, year] = date.split('/');
        return `${day}-${month}-${year}`;
    }
);

console.log(result); // "Meeting scheduled for 15-11-2023 and follow-up on 01-12-2023"

Análisis y extracción de información

JavaScript permite implementar analizadores sofisticados para extraer información estructurada:

  • Extracción de múltiples ocurrencias
// Extraer todas las URLs de un texto
function extractURLs(text) {
    const urlRegex = /https?:\/\/[^\s]+/g;
    return text.match(urlRegex) || [];
}

const content = "Check out https://developer.mozilla.org and https://javascript.info for resources.";
console.log(extractURLs(content));
// ["https://developer.mozilla.org", "https://javascript.info"]
  • Análisis de texto estructurado
// Analizar un string CSV simple
function parseCSV(text, delimiter = ',') {
    const rows = text.trim().split('\n');
    return rows.map(row => {
        // Manejo básico de campos entre comillas
        const fields = [];
        let inQuotes = false;
        let currentField = '';
        
        for (let i = 0; i < row.length; i++) {
            const char = row[i];
            
            if (char === '"') {
                inQuotes = !inQuotes;
            } else if (char === delimiter && !inQuotes) {
                fields.push(currentField);
                currentField = '';
            } else {
                currentField += char;
            }
        }
        
        fields.push(currentField); // Añadir el último campo
        return fields;
    });
}

const csvData = `name,age,city
"Smith, John",42,New York
Alice Brown,28,"San Francisco, CA"`;

console.log(parseCSV(csvData));
// [
//   ["name", "age", "city"],
//   ["Smith, John", "42", "New York"],
//   ["Alice Brown", "28", "San Francisco, CA"]
// ]
  • Tokenización de texto
// Tokenizar un texto en palabras, respetando puntuación
function tokenize(text) {
    // Dividir por espacios pero mantener puntuación como tokens separados
    return text.match(/\w+|[^\w\s]/g) || [];
}

const sentence = "Hello, world! This is a test.";
console.log(tokenize(sentence));
// ["Hello", ",", "world", "!", "This", "is", "a", "test", "."]

Manipulación de formato y presentación

  • Truncado inteligente de texto
// Truncar texto sin cortar palabras
function smartTruncate(text, maxLength, suffix = '...') {
    if (text.length <= maxLength) return text;
    
    // Encontrar el último espacio antes del límite
    const truncated = text.slice(0, maxLength);
    const lastSpace = truncated.lastIndexOf(' ');
    
    if (lastSpace === -1) return truncated + suffix;
    return truncated.slice(0, lastSpace) + suffix;
}

const description = "JavaScript is a programming language that is one of the core technologies of the World Wide Web.";
console.log(smartTruncate(description, 50));
// "JavaScript is a programming language that is one..."
  • Formateo de números
// Formatear números con separadores de miles
function formatNumber(num) {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

console.log(formatNumber(1234567.89)); // "1,234,567.89"

// Usando las API nativas de JavaScript
function formatCurrency(amount, currency = 'USD', locale = 'en-US') {
    return new Intl.NumberFormat(locale, {
        style: 'currency',
        currency: currency
    }).format(amount);
}

console.log(formatCurrency(1234.56, 'EUR', 'de-DE')); // "1.234,56 €"
console.log(formatCurrency(1234.56)); // "$1,234.56"
  • Justificación y alineación de texto
// Crear texto justificado (alineado a ambos lados)
function justify(text, width) {
    const words = text.split(' ');
    const lines = [];
    let currentLine = [];
    let currentLength = 0;
    
    // Distribuir palabras en líneas
    for (const word of words) {
        if (currentLength + word.length + currentLine.length <= width) {
            currentLine.push(word);
            currentLength += word.length;
        } else {
            lines.push(currentLine);
            currentLine = [word];
            currentLength = word.length;
        }
    }
    
    if (currentLine.length > 0) {
        lines.push(currentLine);
    }
    
    // Justificar cada línea excepto la última
    return lines.map((line, index) => {
        if (index === lines.length - 1 || line.length === 1) {
            // No justificar la última línea o líneas con una sola palabra
            return line.join(' ');
        }
        
        const totalSpaces = width - line.reduce((sum, word) => sum + word.length, 0);
        const gaps = line.length - 1;
        const spacesPerGap = Math.floor(totalSpaces / gaps);
        let extraSpaces = totalSpaces - (spacesPerGap * gaps);
        
        let result = '';
        for (let i = 0; i < line.length - 1; i++) {
            result += line[i];
            const spaces = spacesPerGap + (extraSpaces > 0 ? 1 : 0);
            result += ' '.repeat(spaces);
            extraSpaces--;
        }
        
        result += line[line.length - 1];
        return result;
    }).join('\n');
}

const paragraph = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";
console.log(justify(paragraph, 30));
// Output:
// Lorem  ipsum  dolor  sit amet,
// consectetur adipiscing   elit.
// Sed  do  eiusmod tempor incid
// idunt  ut  labore  et  dolore
// magna aliqua.

Técnicas de rendimiento para manipulación de strings

Cuando trabajamos con strings grandes o realizamos muchas operaciones, el rendimiento se vuelve crucial:

  • Concatenación eficiente
// Ineficiente para muchas concatenaciones
function buildStringBad(items) {
    let result = '';
    for (const item of items) {
        result += item + ', '; // Crea un nuevo string en cada iteración
    }
    return result.slice(0, -2); // Eliminar la última coma y espacio
}

// Más eficiente
function buildStringGood(items) {
    return items.join(', '); // Mucho más rápido para arrays grandes
}

// Para construcciones complejas, usar array y join
function buildHTML(data) {
    const parts = [];
    
    parts.push('<ul>');
    for (const item of data) {
        parts.push(`  <li id="${item.id}">${item.name}</li>`);
    }
    parts.push('</ul>');
    
    return parts.join('\n');
}
  • Uso de StringBuffer para grandes volúmenes

Para manipulaciones muy grandes, podemos implementar un patrón similar a StringBuffer:

class StringBuffer {
    constructor(initialCapacity = 16) {
        this.buffer = new Array(initialCapacity);
        this.index = 0;
    }
    
    append(str) {
        // Expandir buffer si es necesario
        if (this.index >= this.buffer.length) {
            const newBuffer = new Array(this.buffer.length * 2);
            for (let i = 0; i < this.buffer.length; i++) {
                newBuffer[i] = this.buffer[i];
            }
            this.buffer = newBuffer;
        }
        
        this.buffer[this.index++] = str;
        return this;
    }
    
    toString() {
        return this.buffer.slice(0, this.index).join('');
    }
}

// Ejemplo de uso
function generateLargeText(repetitions) {
    const buffer = new StringBuffer();
    
    for (let i = 0; i < repetitions; i++) {
        buffer.append(`Line ${i + 1}: `).append('Some repeated text. ');
    }
    
    return buffer.toString();
}

// Mucho más eficiente que concatenación para grandes volúmenes
const largeText = generateLargeText(10000);
  • Procesamiento por lotes

Para strings extremadamente grandes, procesar por fragmentos:

// Procesar un string muy grande por fragmentos
function countWordsInLargeText(text, batchSize = 10000) {
    let wordCount = 0;
    let position = 0;
    
    while (position < text.length) {
        // Extraer un fragmento
        const chunk = text.slice(position, position + batchSize);
        
        // Encontrar límite de palabra completa
        let endPos = batchSize;
        if (position + batchSize < text.length) {
            const nextSpacePos = chunk.lastIndexOf(' ');
            if (nextSpacePos !== -1) {
                endPos = nextSpacePos + 1;
            }
        }
        
        // Contar palabras en este fragmento
        const words = chunk.slice(0, endPos).match(/\S+/g) || [];
        wordCount += words.length;
        
        // Avanzar posición
        position += endPos;
    }
    
    return wordCount;
}

// Ejemplo con un texto grande
const longText = "Lorem ipsum ".repeat(100000);
console.log(countWordsInLargeText(longText)); // 200000

Internacionalización y localización

JavaScript ofrece potentes APIs para trabajar con texto en diferentes idiomas:

  • Formateo sensible al idioma
// Formatear fechas según la localización
function formatDate(date, locale = 'en-US') {
    return new Intl.DateTimeFormat(locale, {
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    }).format(date);
}

const today = new Date();
console.log(formatDate(today, 'en-US')); // "November 15, 2023"
console.log(formatDate(today, 'es-ES')); // "15 de noviembre de 2023"
console.log(formatDate(today, 'ja-JP')); // "2023年11月15日"
  • Comparación de strings sensible al idioma
// Ordenar strings respetando reglas específicas del idioma
function sortByLocale(strings, locale) {
    return [...strings].sort((a, b) => a.localeCompare(b, locale));
}

const words = ['café', 'apple', 'ñandú', 'zebra'];

console.log(sortByLocale(words, 'en-US'));
// ["apple", "café", "ñandú", "zebra"]

console.log(sortByLocale(words, 'es-ES'));
// ["apple", "café", "ñandú", "zebra"] (ñ viene después de n en español)
  • Pluralización y reglas gramaticales
// Pluralización correcta según el idioma
function formatWithCount(count, singular, plural, locale = 'en-US') {
    return new Intl.PluralRules(locale).select(count) === 'one'
        ? `${count} ${singular}`
        : `${count} ${plural}`;
}

console.log(formatWithCount(1, 'item', 'items')); // "1 item"
console.log(formatWithCount(5, 'item', 'items')); // "5 items"

// Usando la API completa de Intl para mensajes
function getLocalizedMessage(count, locale = 'en-US') {
    const pluralForm = new Intl.PluralRules(locale).select(count);
    
    const messages = {
        'en-US': {
            'one': `You have ${count} new message.`,
            'other': `You have ${count} new messages.`
        },
        'ru-RU': {
            'one': `У вас ${count} новое сообщение.`,
            'few': `У вас ${count} новых сообщения.`,
            'many': `У вас ${count} новых сообщений.`,
            'other': `У вас ${count} новых сообщений.`
        }
    };
    
    return messages[locale][pluralForm] || messages[locale]['other'];
}

console.log(getLocalizedMessage(1, 'en-US')); // "You have 1 new message."
console.log(getLocalizedMessage(5, 'en-US')); // "You have 5 new messages."

La manipulación avanzada de strings en JavaScript combina técnicas algorítmicas, expresiones regulares sofisticadas y APIs nativas para resolver problemas complejos de procesamiento de texto. Dominar estas técnicas permite crear aplicaciones robustas que manejan texto de manera eficiente y elegante, independientemente de la complejidad o el volumen de los datos.

Strings en JavaScript moderno

JavaScript ha evolucionado significativamente en los últimos años, introduciendo características modernas que mejoran considerablemente el trabajo con strings. Estas nuevas funcionalidades hacen que la manipulación de texto sea más expresiva, concisa y potente, permitiendo resolver problemas complejos con menos código y mayor legibilidad.

Template literals

Los template literals (introducidos en ES6) representan una de las mejoras más significativas en el manejo de strings:

// Sintaxis tradicional
const name = "Alice";
const greeting = "Hello, " + name + "!";

// Template literals
const modernGreeting = `Hello, ${name}!`;

Los template literals ofrecen varias ventajas importantes:

  • Interpolación de expresiones

Permiten insertar cualquier expresión JavaScript válida:

const product = {
  name: "Laptop",
  price: 999,
  discount: 0.15
};

const priceTag = `${product.name}: $${product.price} (Save $${(product.price * product.discount).toFixed(2)})`;
console.log(priceTag); // "Laptop: $999 (Save $149.85)"
  • Strings multilínea

Facilitan la creación de texto con saltos de línea sin necesidad de caracteres de escape:

const html = `
<div class="card">
  <h2>Product Details</h2>
  <p>Check out our latest offers</p>
</div>
`;
  • Tagged templates

Permiten procesar template literals con funciones personalizadas:

function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const value = values[i] || '';
    return `${result}${str}${value ? `<span class="highlight">${value}</span>` : ''}`;
  }, '');
}

const keyword = "JavaScript";
const text = highlight`Learn ${keyword} in 2023 and boost your career!`;
// "Learn <span class="highlight">JavaScript</span> in 2023 and boost your career!"

Esta técnica es la base de bibliotecas populares como styled-components y graphql-tag.

String.raw

El método String.raw es una función de etiqueta (tag function) que devuelve el texto sin procesar de los template literals, ignorando los caracteres de escape:

// Normalmente, \n crea un salto de línea
console.log(`First line\nSecond line`);
// First line
// Second line

// Con String.raw, los caracteres de escape se preservan literalmente
console.log(String.raw`First line\nSecond line`);
// "First line\nSecond line"

Esto es especialmente útil cuando trabajamos con expresiones regulares o rutas de archivo:

// Sin String.raw, necesitaríamos doble escape
const windowsPath = "C:\\Users\\Admin\\Documents";

// Con String.raw, es más legible
const betterPath = String.raw`C:\Users\Admin\Documents`;

Nuevos métodos de búsqueda y comprobación

JavaScript moderno ha introducido métodos más intuitivos para verificar la presencia de substrings:

  • includes()
const message = "JavaScript is amazing";

// Forma antigua
const hasWord = message.indexOf("amazing") !== -1;

// Forma moderna
const containsWord = message.includes("amazing"); // true
  • startsWith() y endsWith()
const filename = "report.pdf";

// Verificar extensión
if (filename.endsWith(".pdf")) {
  console.log("This is a PDF file");
}

// Verificar prefijo
const urls = ["https://example.com", "http://test.org", "ftp://files.net"];
const secureUrls = urls.filter(url => url.startsWith("https://"));

Estos métodos también aceptan un segundo parámetro opcional para especificar la posición:

const text = "React and Vue are popular frameworks";
console.log(text.startsWith("Vue", 10)); // true
console.log(text.endsWith("React", 5)); // true

Métodos de relleno y alineación

Para formatear texto con longitud específica, JavaScript moderno ofrece métodos de padding:

  • padStart() y padEnd()
// Formatear números de tarjeta de crédito
const lastFourDigits = "5678";
const maskedCardNumber = lastFourDigits.padStart(16, "*");
console.log(maskedCardNumber); // "************5678"

// Crear columnas alineadas
const column1 = "Name".padEnd(15, " ");
const column2 = "Price".padEnd(10, " ");
const column3 = "Stock";

console.log(`${column1}${column2}${column3}`);
// "Name           Price     Stock"

Estos métodos son particularmente útiles para:

  • Formatear datos tabulares
  • Crear identificadores con longitud fija
  • Alinear texto en interfaces de consola
  • Formatear números con ceros a la izquierda
// Formatear fechas
const day = "7";
const month = "9";
const year = "2023";

const formattedDate = `${day.padStart(2, "0")}/${month.padStart(2, "0")}/${year}`;
console.log(formattedDate); // "07/09/2023"

Métodos de recorte mejorados

JavaScript moderno ofrece métodos más específicos para eliminar espacios en blanco:

const input = "   user@example.com   ";

// Método tradicional
const trimmedOld = input.trim();

// Métodos modernos
const trimmedStart = input.trimStart(); // "user@example.com   "
const trimmedEnd = input.trimEnd();     // "   user@example.com"

Estos métodos también son conocidos por sus alias trimLeft() y trimRight(), aunque se recomienda usar los nombres estándar.

replaceAll() para reemplazos globales

Uno de los métodos más recientes (ES2021) es replaceAll(), que simplifica enormemente los reemplazos múltiples:

const paragraph = "The quick brown fox jumps over the lazy dog. The fox is quick.";

// Forma antigua con expresión regular
const oldWay = paragraph.replace(/fox/g, "wolf");

// Forma moderna
const newWay = paragraph.replaceAll("fox", "wolf");
// "The quick brown wolf jumps over the lazy dog. The wolf is quick."

Este método acepta tanto strings como expresiones regulares (con flag global):

// Reemplazar múltiples patrones
const code = "const x = 10; let y = 20;";
const es5code = code.replaceAll(/const|let/g, "var");
// "var x = 10; var y = 20;"

La ventaja principal de replaceAll() es su claridad y simplicidad cuando se trabaja con strings literales, evitando la necesidad de expresiones regulares para casos sencillos.

Métodos de iteración de caracteres

Para trabajar correctamente con caracteres Unicode, especialmente con emojis y otros caracteres que ocupan múltiples unidades de código, JavaScript moderno ofrece mejores herramientas:

const text = "😊👨‍👩‍👧‍👦🇪🇸";

// Iteración incorrecta (divide caracteres compuestos)
for (let i = 0; i < text.length; i++) {
  console.log(text[i]); // Muestra fragmentos de caracteres
}

// Iteración correcta con for...of
for (const char of text) {
  console.log(char); // "😊", "👨‍👩‍👧‍👦", "🇪🇸"
}

// Convertir a array de caracteres Unicode correctamente
const chars = [...text];
console.log(chars.length); // 3 (cuenta caracteres visibles correctamente)

El operador spread (...) y el bucle for...of respetan los límites de caracteres Unicode, lo que los hace ideales para trabajar con texto internacional.

Internacionalización con Intl

La API Intl proporciona capacidades avanzadas de internacionalización para strings:

1. Comparación y ordenación sensible al idioma

const names = ["Ángel", "Zoe", "Ñoño", "Adrian"];

// Ordenación que respeta reglas específicas del idioma
names.sort((a, b) => a.localeCompare(b, "es-ES"));
console.log(names); // ["Adrian", "Ángel", "Ñoño", "Zoe"]

2. Formateo de fechas y números

// Formateo de números según la localización
const formatter = new Intl.NumberFormat("de-DE", {
  style: "currency",
  currency: "EUR"
});

console.log(formatter.format(1234.56)); // "1.234,56 €"

// Formateo de fechas
const date = new Date();
const dateFormatter = new Intl.DateTimeFormat("ja-JP", {
  dateStyle: "full",
  timeStyle: "long"
});

console.log(dateFormatter.format(date)); // Formato japonés completo

3. Pluralización y reglas gramaticales

const pluralRules = new Intl.PluralRules("ru-RU");

function getMessageByCount(count) {
  const rule = pluralRules.select(count);
  const messages = {
    one: `${count} сообщение`,
    few: `${count} сообщения`,
    many: `${count} сообщений`,
    other: `${count} сообщений`
  };
  
  return messages[rule];
}

console.log(getMessageByCount(1)); // "1 сообщение"
console.log(getMessageByCount(3)); // "3 сообщения"
console.log(getMessageByCount(5)); // "5 сообщений"

4. Segmentación de texto

La API Intl.Segmenter (relativamente nueva) permite dividir texto en segmentos lingüísticamente significativos:

// Solo disponible en navegadores modernos
if (typeof Intl.Segmenter === "function") {
  const segmenter = new Intl.Segmenter("en", { granularity: "word" });
  const text = "Hello, world! How are you?";
  const segments = [...segmenter.segment(text)];
  
  // Extraer solo palabras
  const words = segments
    .filter(segment => segment.isWordLike)
    .map(segment => segment.segment);
    
  console.log(words); // ["Hello", "world", "How", "are", "you"]
}

Mejoras en expresiones regulares

JavaScript moderno ha introducido características avanzadas para expresiones regulares que mejoran el trabajo con strings:

1. Flag 's' (dotAll)

Permite que el punto coincida con cualquier carácter, incluidos saltos de línea:

const multiline = `First line
Second line`;

// Sin flag 's', el punto no coincide con saltos de línea
console.log(/First.*Second/.test(multiline)); // false

// Con flag 's', el punto coincide con cualquier carácter
console.log(/First.*Second/s.test(multiline)); // true

2. Grupos de captura nombrados

Permiten acceder a grupos capturados por nombre en lugar de por índice:

const regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = "2023-11-15".match(regex);

// Acceso tradicional por índice
console.log(`${match[3]}/${match[2]}/${match[1]}`); // "15/11/2023"

// Acceso moderno por nombre
const { year, month, day } = match.groups;
console.log(`${day}/${month}/${year}`); // "15/11/2023"

3. Lookbehind assertions

Permiten comprobar lo que precede a un patrón:

// Capturar números que estén precedidos por un símbolo $
const priceRegex = /(?<=\$)\d+(\.\d{2})?/g;
const text = "Products: $25.99, €30.50, $15";
console.log(text.match(priceRegex)); // ["25.99", "15"]

Codificación y decodificación de strings

JavaScript moderno ofrece métodos mejorados para codificar y decodificar strings:

  • encodeURI y decodeURI

Para trabajar con URLs completas:

const url = "https://example.com/search?q=JavaScript strings & encoding";
const encoded = encodeURI(url);
console.log(encoded); // "https://example.com/search?q=JavaScript%20strings%20&%20encoding"
  • encodeURIComponent y decodeURIComponent

Para componentes individuales de URL:

const query = "JavaScript strings & encoding";
const encodedQuery = encodeURIComponent(query);
console.log(encodedQuery); // "JavaScript%20strings%20%26%20encoding"

const url = `https://example.com/search?q=${encodedQuery}`;
  • TextEncoder y TextDecoder

Para conversiones entre strings y datos binarios:

// Codificar string a bytes (Uint8Array)
const encoder = new TextEncoder();
const text = "Hello, 世界";
const bytes = encoder.encode(text);
console.log(bytes); // Uint8Array(13) [72, 101, 108, 108, 111, 44, 32, 228, 184, 150, 231, 149, 140]

// Decodificar bytes a string
const decoder = new TextDecoder();
const decodedText = decoder.decode(bytes);
console.log(decodedText); // "Hello, 世界"

Estas APIs son especialmente útiles cuando se trabaja con WebSockets, Fetch API o cualquier operación que requiera manipulación de datos binarios.

Optimización de rendimiento

JavaScript moderno ofrece patrones más eficientes para operaciones con strings:

1. Concatenación eficiente

// Ineficiente para muchas concatenaciones
let result = '';
for (let i = 0; i < 1000; i++) {
  result += `Item ${i}, `;
}

// Más eficiente con array y join
const parts = [];
for (let i = 0; i < 1000; i++) {
  parts.push(`Item ${i}`);
}
const efficientResult = parts.join(', ');

2. Uso de métodos nativos en lugar de expresiones regulares

const url = "https://example.com/path";

// Menos eficiente
const hasHttps = /^https:/.test(url);

// Más eficiente
const hasHttpsEfficient = url.startsWith("https:");

3. Procesamiento por lotes para strings grandes

function processLargeString(text, batchSize = 10000) {
  let result = '';
  
  for (let i = 0; i < text.length; i += batchSize) {
    const chunk = text.slice(i, i + batchSize);
    // Procesar chunk...
    result += processChunk(chunk);
  }
  
  return result;
}

Integración con otras APIs modernas

Los strings en JavaScript moderno se integran perfectamente con otras APIs avanzadas:

1. Streams API

async function processTextStream(response) {
  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let text = '';
  
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    
    // Convertir chunks de bytes a texto
    text += decoder.decode(value, { stream: true });
    
    // Procesar texto a medida que llega
    processChunk(text);
  }
  
  // Asegurar que se procesen los bytes finales
  text += decoder.decode();
  return text;
}

// Ejemplo de uso con fetch
fetch('https://example.com/large-text-file')
  .then(processTextStream)
  .then(finalText => console.log('Procesamiento completo'));

2. Blob y File API

// Convertir string a Blob
const text = "Hello, world!";
const blob = new Blob([text], { type: 'text/plain' });

// Crear URL para descarga
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = 'hello.txt';
link.click();

// Leer texto de un archivo
document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
  const file = e.target.files[0];
  const text = await file.text(); // Método moderno para leer como texto
  console.log(text);
});

3. Web Workers

// En el script principal
const worker = new Worker('text-processor.js');

worker.postMessage({
  action: 'process',
  text: largeText
});

worker.onmessage = (e) => {
  console.log('Resultado procesado:', e.data.result);
};

// En text-processor.js (Web Worker)
self.onmessage = (e) => {
  if (e.data.action === 'process') {
    const result = processLargeText(e.data.text);
    self.postMessage({ result });
  }
};

function processLargeText(text) {
  // Procesamiento intensivo sin bloquear la UI
  return text.split(' ').length;
}

Strings y estructuras de datos modernas

JavaScript moderno facilita la conversión entre strings y otras estructuras de datos:

1. Map y Set con strings

// Contar frecuencia de palabras
function wordFrequency(text) {
  const words = text.toLowerCase().match(/\w+/g) || [];
  const frequency = new Map();
  
  for (const word of words) {
    frequency.set(word, (frequency.get(word) || 0) + 1);
  }
  
  return frequency;
}

const text = "To be or not to be, that is the question.";
const freq = wordFrequency(text);

// Obtener las 3 palabras más frecuentes
const topWords = [...freq.entries()]
  .sort((a, b) => b[1] - a[1])
  .slice(0, 3);
  
console.log(topWords);
// [["to", 2], ["be", 2], ["or", 1]]

2. Destructuring con strings

// Extraer caracteres específicos
const [first, second, ...rest] = "Hello";
console.log(first); // "H"
console.log(second); // "e"
console.log(rest); // ["l", "l", "o"]

// Combinar con spread
const greeting = "Hello";
const expanded = [...greeting, "!"].join("");
console.log(expanded); // "Hello!"

Strings y programación funcional

JavaScript moderno permite aplicar técnicas de programación funcional a la manipulación de strings:

// Pipeline de transformaciones de texto
const transformText = text => 
  text
    .toLowerCase()
    .split(' ')
    .map(word => word.charAt(0).toUpperCase() + word.slice(1))
    .join(' ')
    .trim();

console.log(transformText("  javaScript string METHODS  "));
// "Javascript String Methods"

Con la propuesta de operador pipeline (aún no estándar pero disponible en algunos entornos con transpilación):

// Con operador pipeline (requiere transpilación)
const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
const removeExtraSpaces = str => str.replace(/\s+/g, ' ').trim();
const splitWords = str => str.split(' ');
const joinWords = words => words.join(' ');

const processText = text => 
  text
  |> removeExtraSpaces
  |> splitWords
  |> words => words.map(capitalize)
  |> joinWords;

console.log(processText("  javaScript string METHODS  "));
// "Javascript String Methods"

Propuestas futuras para strings

Aunque no son parte del estándar actual, hay propuestas interesantes para mejorar aún más el trabajo con strings:

1. String.prototype.replaceAll() (ya implementado en ES2021)

2. String.prototype.matchAll() (ya implementado en ES2020)

const text = "test1test2test3";
const pattern = /test(\d)/g;
const matches = [...text.matchAll(pattern)];

console.log(matches.map(match => match[1])); // ["1", "2", "3"]

3. Método at() para indexación relativa (ya implementado)

const str = "JavaScript";
console.log(str.at(-1)); // "t" (último carácter)
console.log(str.at(-2)); // "p" (penúltimo carácter)

4. Propuesta de método .item() (en consideración)

const str = "Hello";
console.log(str.item(1)); // "e"
console.log(str.item(-1)); // "o" (desde el final)

JavaScript continúa evolucionando, y con cada nueva versión se introducen características que hacen que el trabajo con strings sea más intuitivo, eficiente y potente. Mantenerse al día con estas características modernas no solo mejora la calidad del código, sino que también aumenta la productividad del desarrollador al proporcionar herramientas más expresivas para manipular texto.

CONSTRUYE TU CARRERA EN IA Y PROGRAMACIÓN SOFTWARE

Accede a +1000 lecciones y cursos con certificado. Mejora tu portfolio con certificados de superación para tu CV.

30 % DE DESCUENTO

Plan mensual

19.00 /mes

13.30 € /mes

Precio normal mensual: 19 €
63 % DE DESCUENTO

Plan anual

10.00 /mes

7.00 € /mes

Ahorras 144 € al año
Precio normal anual: 120 €
Aprende JavaScript online

Ejercicios de esta lección Métodos de Strings

Evalúa tus conocimientos de esta lección Métodos de Strings con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Funciones flecha

JavaScript
Puzzle

Polimorfismo

JavaScript
Test

Array

JavaScript
Código

Transformación con map()

JavaScript
Test

Gestor de tareas con JavaScript

JavaScript
Proyecto

Manipulación DOM

JavaScript
Test

Funciones

JavaScript
Test

Funciones flecha

JavaScript
Código

Async / Await

JavaScript
Código

Creación y uso de variables

JavaScript
Test

Excepciones

JavaScript
Puzzle

Promises

JavaScript
Código

Funciones cierre (closure)

JavaScript
Test

Herencia

JavaScript
Puzzle

Herencia

JavaScript
Test

Estructuras de control

JavaScript
Código

Selección de elementos DOM

JavaScript
Test

Modificación de elementos DOM

JavaScript
Test

Filtrado con filter() y find()

JavaScript
Test

Funciones cierre (closure)

JavaScript
Puzzle

Funciones

JavaScript
Puzzle

Mapas con Map

JavaScript
Test

Reducción con reduce()

JavaScript
Test

Callbacks

JavaScript
Puzzle

Manipulación DOM

JavaScript
Puzzle

Promises

JavaScript
Test

Async / Await

JavaScript
Test

Eventos del DOM

JavaScript
Puzzle

Async / Await

JavaScript
Puzzle

Promises

JavaScript
Puzzle

Filtrado con filter() y find()

JavaScript
Código

Callbacks

JavaScript
Test

Creación de clases y objetos Restaurante

JavaScript
Código

Reducción con reduce()

JavaScript
Código

Filtrado con filter() y find()

JavaScript
Puzzle

Reducción con reduce()

JavaScript
Puzzle

Conjuntos con Set

JavaScript
Puzzle

Herencia de clases

JavaScript
Código

Eventos del DOM

JavaScript
Test

Clases y objetos

JavaScript
Puzzle

Modificación de elementos DOM

JavaScript
Puzzle

Mapas con Map

JavaScript
Puzzle

Introducción a JavaScript

JavaScript
Test

Funciones

JavaScript
Código

Tipos de datos

JavaScript
Test

Clases y objetos

JavaScript
Test

Array

JavaScript
Test

Conjuntos con Set

JavaScript
Test

Array

JavaScript
Puzzle

Encapsulación

JavaScript
Puzzle

Clases y objetos

JavaScript
Código

Uso de operadores

JavaScript
Puzzle

Uso de operadores

JavaScript
Test

Estructuras de control

JavaScript
Test

Excepciones

JavaScript
Test

Transformación con map()

JavaScript
Puzzle

Funciones flecha

JavaScript
Test

Selección de elementos DOM

JavaScript
Puzzle

Encapsulación

JavaScript
Test

Mapas con Map

JavaScript
Código

Creación y uso de variables

JavaScript
Puzzle

Polimorfismo

JavaScript
Puzzle

Tipos de datos

JavaScript
Puzzle

Estructuras de control

JavaScript
Puzzle

Todas las lecciones de JavaScript

Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a JavaScript y certifícate

Certificados de superación de JavaScript

Supera todos los ejercicios de programación del curso de JavaScript y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender la diferencia entre un string y un carácter en JavaScript.
  2. Utilizar la propiedad length para conocer el número de caracteres.
  3. Acceder a caracteres individuales usando corchetes o charAt().
  4. Buscar substrings con métodos como indexOf(), includes(), y startsWith().
  5. Extraer partes de un string usando slice(), substring(), y substr().
  6. Comparar strings mediante charCodeAt() y localeCompare().
  7. Concatenar strings con el operador +, concat(), y template literals.