En JavaScript, los datos textuales se almacenan como cadenas. No existe un tipo separado para un solo carácter.
El formato interno de las cadenas es siempre UTF-16 y no está vinculado a la codificación de la página.
Recordemos los tipos de citas.
Las cadenas se pueden encerrar entre comillas simples, comillas dobles o comillas invertidas:
let single = 'comilla simple'; let double = "comillas dobles"; let comillas invertidas = `comillas invertidas`;
Las comillas simples y dobles son esencialmente lo mismo. Las comillas invertidas, sin embargo, nos permiten incrustar cualquier expresión en la cadena, envolviéndola en ${…}
:
función suma(a, b) { devolver a + b; } alerta(`1 + 2 = ${suma(1, 2)}.`); // 1 + 2 = 3.
Otra ventaja de utilizar comillas invertidas es que permiten que una cadena abarque varias líneas:
let lista de invitados = `Invitados: * John * Pete * María `; alerta(lista de invitados); // una lista de invitados, varias líneas
Parece natural, ¿verdad? Pero las comillas simples o dobles no funcionan de esta manera.
Si los usamos e intentamos usar varias líneas, habrá un error:
let guestList = "Invitados: // Error: token inesperado ILEGAL * John";
Las comillas simples y dobles provienen de la antigüedad de la creación del lenguaje, cuando no se tenía en cuenta la necesidad de cadenas de varias líneas. Las comillas invertidas aparecieron mucho más tarde y, por tanto, son más versátiles.
Las comillas invertidas también nos permiten especificar una "función de plantilla" antes de la primera comillas invertidas. La sintaxis es: func`string`
. La función func
se llama automáticamente, recibe la cadena y las expresiones incrustadas y puede procesarlas. Esta característica se llama "plantillas etiquetadas", rara vez se ve, pero puedes leer sobre ella en MDN: Literales de plantilla.
Todavía es posible crear cadenas de varias líneas con comillas simples y dobles utilizando el llamado “carácter de nueva línea”, escrito como n
, que denota un salto de línea:
let guestList = "Invitados:n * Johnn * Peten * Mary"; alerta(lista de invitados); // una lista de invitados de varias líneas, igual que arriba
Como ejemplo más simple, estas dos líneas son iguales, solo que se escriben de manera diferente:
let str1 = "HolanMundo"; // dos líneas usando un "símbolo de nueva línea" // dos líneas usando una nueva línea normal y comillas invertidas let str2 = `Hola Mundo`; alerta(cadena1 == cadena2); // verdadero
Hay otros caracteres especiales menos comunes:
Personaje | Descripción |
---|---|
n | Nueva linea |
r | En los archivos de texto de Windows, una combinación de dos caracteres rn representa una nueva ruptura, mientras que en sistemas operativos que no son Windows es solo n . Por razones históricas, la mayoría del software de Windows también entiende n . |
' , " , ` | Citas |
\ | Barra invertida |
t | Pestaña |
b , f , v | Retroceso, avance de formulario, pestaña vertical: mencionados para que estén completos, provienen de tiempos antiguos, no se usan hoy en día (puedes olvidarlos ahora mismo). |
Como puede ver, todos los caracteres especiales comienzan con una barra invertida . También se le llama "personaje de escape".
Debido a que es tan especial, si necesitamos mostrar una barra invertida real dentro de la cadena, debemos duplicarla:
alert(`La barra invertida: \`); // La barra invertida:
Las llamadas comillas "escapadas" '
, "
, `
se utilizan para insertar una comilla en la misma cadena entre comillas.
Por ejemplo:
alerta ('¡Soy la morsa!'); // ¡Soy la Morsa!
Como puede ver, tenemos que anteponer la comilla interna con la barra invertida '
, porque de lo contrario indicaría el final de la cadena.
Por supuesto, sólo es necesario escapar las comillas que son iguales a las adjuntas. Entonces, como solución más elegante, podríamos cambiar a comillas dobles o comillas invertidas:
alerta ("¡Soy la morsa!"); // ¡Soy la Morsa!
Además de estos caracteres especiales, también hay una notación especial para códigos Unicode u…
, rara vez se usa y se trata en el capítulo opcional sobre Unicode.
La propiedad length
tiene la longitud de la cadena:
alerta(`Min`.longitud); // 3
Tenga en cuenta que n
es un único carácter "especial", por lo que la longitud es de hecho 3
.
length
es una propiedad.
Las personas con experiencia en otros idiomas a veces escriben mal llamando str.length()
en lugar de simplemente str.length
. Eso no funciona.
Tenga en cuenta que str.length
es una propiedad numérica, no una función. No es necesario agregar paréntesis después. No .length()
, sino .length
.
Para obtener un carácter en la posición pos
, use corchetes [pos]
o llame al método str.at(pos). El primer carácter comienza desde la posición cero:
let str = `Hola`; // el primer carácter alerta (cadena [0]); //H alerta( str.at(0) ); //H // el último carácter alerta (cadena [cadena.longitud - 1]); //o alerta( str.at(-1) );
Como puede ver, el método .at(pos)
tiene la ventaja de permitir una posición negativa. Si pos
es negativo, se cuenta desde el final de la cadena.
Entonces .at(-1)
significa el último carácter y .at(-2)
es el anterior, etc.
Los corchetes siempre devuelven undefined
para índices negativos, por ejemplo:
let str = `Hola`; alerta (cadena [-2]); // indefinido alerta( str.at(-2) ); // yo
También podemos iterar sobre personajes usando for..of
:
for (let char de "Hola") { alerta(carbón); // H,e,l,l,o (char se convierte en "H", luego "e", luego "l", etc.) }
Las cadenas no se pueden cambiar en JavaScript. Es imposible cambiar un personaje.
Intentémoslo para demostrar que no funciona:
let str = 'Hola'; cadena[0] = 'h'; // error alerta (cadena [0]); // no funciona
La solución habitual es crear una cadena completamente nueva y asignarla a str
en lugar de a la anterior.
Por ejemplo:
let str = 'Hola'; cadena = 'h' + cadena[1]; // reemplaza la cadena alerta (cadena); // Hola
En las siguientes secciones veremos más ejemplos de esto.
Los métodos toLowerCase() y toUpperCase() cambian el caso:
alerta ('Interfaz'.toUpperCase()); // INTERFAZ alerta ('Interfaz'.toLowerCase()); // interfaz
O, si queremos un solo carácter en minúscula:
alert( 'Interfaz'[0].toLowerCase() ); // 'i'
Hay varias formas de buscar una subcadena dentro de una cadena.
El primer método es str.indexOf(substr, pos).
Busca la substr
en str
, comenzando desde la posición dada pos
y devuelve la posición donde se encontró la coincidencia o -1
si no se puede encontrar nada.
Por ejemplo:
let str = 'Widget con id'; alerta( str.indexOf('Widget') ); // 0, porque 'Widget' se encuentra al principio alerta (str.indexOf ('widget')); // -1, no encontrado, la búsqueda distingue entre mayúsculas y minúsculas alerta( str.indexOf("id") ); // 1, "id" se encuentra en la posición 1 (..idget con id)
El segundo parámetro opcional nos permite comenzar a buscar desde una posición determinada.
Por ejemplo, la primera aparición de "id"
está en la posición 1
. Para buscar la siguiente aparición, comencemos la búsqueda desde la posición 2
:
let str = 'Widget con id'; alerta( str.indexOf('id', 2) ) // 12
Si estamos interesados en todas las ocurrencias, podemos ejecutar indexOf
en un bucle. Cada nueva convocatoria se realiza con la posición posterior al partido anterior:
let str = 'Tan astuto como un zorro, tan fuerte como un buey'; let objetivo = 'como'; // vamos a buscarlo sea pos = 0; mientras (verdadero) { let foundPos = str.indexOf(objetivo, pos); si (foundPos == -1) se rompe; alerta(`Encontrado en ${foundPos}`); pos = pos encontrado + 1; //continuar la búsqueda desde la siguiente posición }
El mismo algoritmo se puede resumir:
let str = "Tan astuto como un zorro, tan fuerte como un buey"; let objetivo = "como"; sea pos = -1; mientras ((pos = str.indexOf(objetivo, pos + 1)) != -1) { alerta (pos); }
str.lastIndexOf(substr, position)
También existe un método similar str.lastIndexOf(substr, position) que busca desde el final de una cadena hasta su principio.
Enumeraría las ocurrencias en orden inverso.
Existe un ligero inconveniente con indexOf
en la prueba if
. No podemos ponerlo en el if
así:
let str = "Widget con id"; si (str.indexOf("Widget")) { alerta("Lo encontramos"); // ¡no funciona! }
La alert
en el ejemplo anterior no se muestra porque str.indexOf("Widget")
devuelve 0
(lo que significa que encontró la coincidencia en la posición inicial). Correcto, pero if
considera que 0
es false
.
Entonces, deberíamos verificar -1
, así:
let str = "Widget con id"; si (str.indexOf("Widget")! = -1) { alerta("Lo encontramos"); // ¡funciona ahora! }
El método más moderno str.includes(substr, pos) devuelve true/false
dependiendo de si str
contiene substr
dentro.
Es la elección correcta si necesitamos probar el partido, pero no necesitamos su posición:
alert("Widget con id".includes("Widget")); // verdadero alerta ("Hola". incluye ("Adiós")); // FALSO
El segundo argumento opcional de str.includes
es la posición desde la que empezar a buscar:
alerta("Widget".includes("id")); // verdadero alerta( "Widget".includes("id", 3) ); //falso, desde la posición 3 no hay "id"
Los métodos str.startsWith y str.endsWith hacen exactamente lo que dicen:
alerta( "Widget".startsWith("Wid") ); // verdadero, "Widget" comienza con "Wid" alerta( "Widget".endsWith("obtener") ); // verdadero, "Widget" termina con "get"
Hay 3 métodos en JavaScript para obtener una subcadena: substring
, substr
y slice
.
str.slice(start [, end])
Devuelve la parte de la cadena desde start
hasta end
(pero sin incluirlo).
Por ejemplo:
let str = "stringificar"; alerta( str.slice(0, 5) ); // 'cadena', la subcadena de 0 a 5 (sin incluir 5) alerta( str.slice(0, 1) ); // 's', de 0 a 1, pero sin incluir 1, por lo que solo el carácter en 0
Si no hay un segundo argumento, entonces slice
va hasta el final de la cadena:
let str = "stringificar"; alerta( str.slice(2) ); // 'ringify', desde la 2ª posición hasta el final
También son posibles valores negativos para start/end
. Significan que la posición se cuenta desde el final de la cuerda:
let str = "stringificar"; // comienza en la 4ª posición desde la derecha, termina en la 1ª posición desde la derecha alerta (str.slice(-4, -1)); // 'gif'
str.substring(start [, end])
Devuelve la parte de la cadena entre start
y end
(sin incluir end
).
Esto es casi lo mismo que slice
, pero permite que start
sea mayor que end
(en este caso simplemente intercambia los valores start
y end
).
Por ejemplo:
let str = "stringificar"; // estos son los mismos para la subcadena alerta( str.substring(2, 6) ); // "anillo" alerta( str.substring(6, 2) ); // "anillo" // ...pero no para el segmento: alerta( str.slice(2, 6) ); // "anillo" (lo mismo) alerta( str.slice(6, 2) ); // "" (una cadena vacía)
Los argumentos negativos (a diferencia del segmento) no se admiten, se tratan como 0
.
str.substr(start [, length])
Devuelve la parte de la cadena desde start
, con la length
dada.
A diferencia de los métodos anteriores, este nos permite especificar la length
en lugar de la posición final:
let str = "stringificar"; alerta( str.substr(2, 4) ); // 'ring', desde la 2ª posición obtenemos 4 caracteres
El primer argumento puede ser negativo, contando desde el final:
let str = "stringificar"; alerta( str.substr(-4, 2) ); // 'gi', desde la 4ª posición obtienes 2 caracteres
Este método reside en el Anexo B de la especificación del lenguaje. Significa que sólo los motores Javascript alojados en el navegador deberían admitirlo y no se recomienda su uso. En la práctica, se admite en todas partes.
Recapitulemos estos métodos para evitar confusiones:
método | selecciona… | negativos |
---|---|---|
slice(start, end) | de start a end (sin incluir end ) | permite negativos |
substring(start, end) | entre start y end (sin incluir end ) | los valores negativos significan 0 |
substr(start, length) | desde start obtener caracteres length | permite start negativo |
¿Cuál elegir?
Todos ellos pueden hacer el trabajo. Formalmente, substr
tiene un pequeño inconveniente: no se describe en la especificación principal de JavaScript, sino en el Anexo B, que cubre características exclusivas del navegador que existen principalmente por razones históricas. Por lo tanto, es posible que los entornos sin navegador no lo admitan. Pero en la práctica funciona en todas partes.
De las otras dos variantes, slice
es un poco más flexible, permite argumentos negativos y es más corto de escribir.
Entonces, para un uso práctico, es suficiente recordar solo slice
.
Como sabemos por el capítulo Comparaciones, las cadenas se comparan carácter por carácter en orden alfabético.
Aunque hay algunas rarezas.
Una letra minúscula siempre es mayor que la mayúscula:
alerta('a' > 'Z'); // verdadero
Las letras con signos diacríticos están “fuera de orden”:
alert( 'Österreich' > 'Zelanda' ); // verdadero
Esto puede generar resultados extraños si ordenamos los nombres de estos países. Por lo general, la gente esperaría que Zealand
estuviera después de Österreich
en la lista.
Para entender lo que sucede, debemos tener en cuenta que las cadenas en Javascript están codificadas usando UTF-16. Es decir: cada carácter tiene un código numérico correspondiente.
Existen métodos especiales que permiten obtener el carácter del código y viceversa:
str.codePointAt(pos)
Devuelve un número decimal que representa el código del carácter en la posición pos
:
// diferentes letras mayúsculas tienen códigos diferentes alerta( "Z".codePointAt(0) ); // 90 alerta( "z".codePointAt(0) ); // 122 alerta( "z".codePointAt(0).toString(16) ); // 7a (si necesitamos un valor hexadecimal)
String.fromCodePoint(code)
Crea un carácter por su code
numérico.
alerta (String.fromCodePoint(90)); //Z alerta (String.fromCodePoint (0x5a)); // Z (también podemos usar un valor hexadecimal como argumento)
Ahora veamos los caracteres con códigos 65..220
(el alfabeto latino y un poquito más) haciendo una cadena con ellos:
let cadena = ''; para (sea i = 65; i <= 220; i++) { str += String.fromCodePoint(i); } alerta (cadena); // Producción: // ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~ € ‚ƒ„ // ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜ
¿Ver? Primero van los caracteres en mayúscula, luego algunos especiales, luego los caracteres en minúscula y Ö
cerca del final de la salida.
Ahora resulta obvio por qué a > Z
.
Los caracteres se comparan por su código numérico. El código mayor significa que el carácter es mayor. El código para a
(97) es mayor que el código para Z
(90).
Todas las letras minúsculas van detrás de las mayúsculas porque sus códigos son mayores.
Algunas letras como Ö
se destacan del alfabeto principal. Aquí, su código es mayor que cualquier cosa desde a
hasta z
.
El algoritmo "correcto" para hacer comparaciones de cadenas es más complejo de lo que parece, porque los alfabetos son diferentes para diferentes idiomas.
Por lo tanto, el navegador necesita conocer el idioma para comparar.
Afortunadamente, los navegadores modernos admiten el estándar de internacionalización ECMA-402.
Proporciona un método especial para comparar cadenas en diferentes idiomas, siguiendo sus reglas.
La llamada str.localeCompare(str2) devuelve un número entero que indica si str
es menor, igual o mayor que str2
según las reglas del lenguaje:
Devuelve un número negativo si str
es menor que str2
.
Devuelve un número positivo si str
es mayor que str2
.
Devuelve 0
si son equivalentes.
Por ejemplo:
alert( 'Österreich'.localeCompare('Zelanda') ); // -1
En realidad, este método tiene dos argumentos adicionales especificados en la documentación, lo que le permite especificar el idioma (de forma predeterminada, tomado del entorno, el orden de las letras depende del idioma) y configurar reglas adicionales como distinción entre mayúsculas y minúsculas o "a"
y "á"
ser tratado como el mismo, etc.
Hay 3 tipos de cotizaciones. Las comillas invertidas permiten que una cadena abarque varias líneas e incruste expresiones ${…}
.
Podemos utilizar caracteres especiales, como un salto de línea n
.
Para obtener un carácter, utilice: []
o el método at
.
Para obtener una subcadena, use: slice
o substring
.
Para poner en minúscula/mayúscula una cadena, utilice: toLowerCase/toUpperCase
.
Para buscar una subcadena, utilice: indexOf
o includes/startsWith/endsWith
para comprobaciones sencillas.
Para comparar cadenas según el idioma, utilice: localeCompare
; de lo contrario, se comparan mediante códigos de caracteres.
Hay varios otros métodos útiles en cadenas:
str.trim()
– elimina (“recorta”) espacios del principio y del final de la cadena.
str.repeat(n)
: repite la cadena n
veces.
…y más se puede encontrar en el manual.
Las cadenas también tienen métodos para buscar/reemplazar con expresiones regulares. Pero ese es un gran tema, por lo que se explica en una sección separada del tutorial Expresiones regulares.
Además, a partir de ahora es importante saber que las cadenas se basan en la codificación Unicode y, por lo tanto, hay problemas con las comparaciones. Hay más información sobre Unicode en el capítulo Unicode, elementos internos de cadenas.
importancia: 5
Escriba una función ucFirst(str)
que devuelva la cadena str
con el primer carácter en mayúscula, por ejemplo:
ucFirst("juan") == "Juan";
Abra una caja de arena con pruebas.
No podemos "reemplazar" el primer carácter porque las cadenas en JavaScript son inmutables.
Pero podemos crear una nueva cadena basada en la existente, con el primer carácter en mayúscula:
let newStr = str[0].toUpperCase() + str.slice(1);
Pero hay un pequeño problema. Si str
está vacío, entonces str[0]
no está undefined
y, como undefined
no tiene el método toUpperCase()
, obtendremos un error.
La salida más sencilla es agregar una prueba para una cadena vacía, como esta:
función ucFirst(cadena) { si (!cadena) devuelve cadena; devolver str[0].toUpperCase() + str.slice(1); } alerta( ucFirst("juan") ); // John
Abra la solución con pruebas en un sandbox.
importancia: 5
Escriba una función checkSpam(str)
que devuelva true
si str
contiene 'viagra' o 'XXX'; en caso contrario, false
.
La función no debe distinguir entre mayúsculas y minúsculas:
checkSpam('comprar ViAgRA ahora') == verdadero checkSpam('xxxxx gratis') == verdadero checkSpam("conejo inocente") == falso
Abra una caja de arena con pruebas.
Para que la búsqueda no distinga entre mayúsculas y minúsculas, pongamos la cadena en minúsculas y luego busquemos:
función verificarSpam(cadena) { let lowerStr = str.toLowerCase(); devolver lowerStr.includes('viagra') || lowerStr.includes('xxx'); } alert( checkSpam('comprar ViAgRA ahora') ); alerta( checkSpam('xxxxx gratis') ); alerta( checkSpam("conejo inocente") );
Abra la solución con pruebas en un sandbox.
importancia: 5
Cree una función truncate(str, maxlength)
que verifique la longitud de str
y, si excede maxlength
, reemplace el final de str
con el carácter de puntos suspensivos "…"
, para que su longitud sea igual a maxlength
.
El resultado de la función debe ser la cadena truncada (si es necesario).
Por ejemplo:
truncate("Lo que me gustaría contar sobre este tema es:", 20) == "Lo que me gustaría contar..." truncate("¡Hola a todos!", 20) == "¡Hola a todos!"
Abra una caja de arena con pruebas.
La longitud máxima debe ser maxlength
, por lo que debemos cortarla un poco más para dejar espacio para los puntos suspensivos.
Tenga en cuenta que en realidad hay un único carácter Unicode para los puntos suspensivos. Eso no son tres puntos.
función truncar (cadena, longitud máxima) { retorno (cadena.longitud > longitud máxima)? str.slice(0, longitud máxima - 1) + '…' : str; }
Abra la solución con pruebas en un sandbox.
importancia: 4
Tenemos un costo en forma de "$120"
. Es decir: primero va el signo del dólar y luego el número.
Cree una función extractCurrencyValue(str)
que extraiga el valor numérico de dicha cadena y lo devuelva.
El ejemplo:
alerta( extraerCurrencyValue('$120') === 120 ); // verdadero
Abra una caja de arena con pruebas.
función extraerValorCurrency(cadena) { retorno +str.slice(1); }
Abra la solución con pruebas en un sandbox.