Las cadenas de caracteres o simplemente cadenas o strings (por su denominación en inglés), son vectores especializados en el manejo de caracteres, es decir en el manejo de texto.
Al ser vectores son datos estructurados, sin embargo, al ser un tipo de dato de uso frecuente, todos los lenguajes de programación disponen de una sintaxis simplificada para las mismas. Como ya se ha visto en el caso de JavaScript (y en la mayoría de los lenguajes de programación) se crean simplemente escribiéndolas entre comillas o apóstrofos y en el caso de JavaScript, también entre acentos invertidos (plantillas literales).
Al igual que ocurre con los números, el valor de la cadena: el texto en sí, es un valor primitivo (no un objeto), sin embargo, desde el mismo se puede llamar a cualquiera de los métodos dinámicos de la clase String, porque JavaScript los convierte automáticamente en objetos.
Al ser objetos, las cadenas pueden ser creadas también con el operador new (new String("cadena")), sin embargo, en la práctica, las cadenas se crean (casi siempre) empleando la notación simplificada.
Al igual que los array, las cadenas tienen la propiedad length, que devuelve el número de caracteres de la cadena, sin embargo, a diferencia de los array, esta propiedad no puede ser modificada (es de sólo lectura).
Además de esta propiedad, las cadenas cuentan con los siguientes métodos:
| Método | Descripción |
|---|---|
| at(i) | Devuelve el carácter que se encuentra en la posición "i" (un carácter utf-16). Si "i" es negativo cuenta desde el último carácter hacía atrás. |
| charAt(i) | Devuelve el carácter que se encuentra en la posición "i" (un carácter utf-16). Si "i" es negativo o mayor al índice del último elemento, devuelve una cadena vacía. |
| charCodeAt(i) | Devuelve el código utf-16 (de 0 a 65535) del carácter que se encuentra en la posición "i". |
| codePointAt(i) | Devuelve el código utf-16, de 0 a 65535 o de 0 a 1114111 (cuando es un pseudo-carácter sustituto), del carácter que se encuentra en la posición "i". |
| concat(s1, s2, ...) | Devuelve una nueva cadena conformada por la cadena desde la cual se llama al método y las cadenas "s1"+"s2"+... (equivalente al uso del operador "+"). |
| endsWith(s [, l]) | Devuelve true, si la cadena desde la cual se llama al método termina con la cadena "s". Opcionalmente puede recibir la longitud de la cadena "l" (por defecto "str.length"). |
| fromCharCode(n) | Método estático que devuelve el carácter correspondiente al código "n" (entre 0 y 65535). |
| fromCodePoint(n1, n2, n3, ...) | Método estático que devuelve una cadena con la secuencia de caracteres equivalentes a los códigos unicode n1, n2, n3, ... (valores comprendidos entre 0 y 1114111). |
| include(s [, i]) | Devuelve true, si la cadena "s" es parte de la cadena desde la cual se llama al método. Opcionalmente puede recibir el índice "i", desde el cual comenzará la búsqueda (por defecto 0). |
| indexOf(s1, i) | Devuelve el índice donde aparece, por primera vez, la subcadena "s1", comenzando la búsqueda en la posición "i" (por defecto desde el primer carácter de la cadena). |
| isWellFormed() | Devuelve true, si la cadena desde la cual se llama al método no contiene ningún código utf-16 incompleto (un código solitario). |
| lastIndexOf(s, i) | Devuelve el índice donde aparece, por primera vez, la cadena "s" dentro de la cadena desde la cual se llama al método, pero búscando la cadena hacia atrás: desde la posición "i" (por defecto desde el último carácter: s.length-1). |
| localeCompare(s [, l [, o]]) | Devuelve un valor positivo si la cadena desde la que se llama al método es menor a "s" (es decir si debe estar antes que "s"), negativo, si es mayor a "s" (debe estar después de "s") y 0 si es igual a "s". Alternativamente puede recibir en "l" (locales) el código del país en el que se basará la comparación y en "o" (opciones) un objeto con opciones adicionales para llevar a cabo la comparación. |
| match(s) | Devuelve un vector con las partes de la cadena que coinciden con la cadena (o expresión regular) "s". Si "s" es una expresión regular e incluye el modificador global "g", devuelve un array con todas las coincidencias. Si no incluye "g", devuelve un array con la primera coincidencia y los grupos de esa coincidencia. |
| matchAll(s) | Devuelve un iterador con todas las coincidencias correspondientes a la expresión regular "s". La expresión regular "s", debe tener el modificador global "g". Cada uno de los elementos del iterador devuelto, es un array con el texto de la coincidencia y los grupos de esa coincidencia. |
| normalize(f) | Devuelve la cadena desde la que se llama al método, normalizada a la forma Unicode "f" (por defecto NFC). |
| padEnd(l [, s]) | Rellena el final de la cadena desde la que se llama al método, con la cadena "s", hasta que la cadena tiene la longitud "l" especificada. Si no se manda "s", la cadena se rellena con espacios en blanco. |
| padStart(l [, s]) | Rellena el principio de la cadena desde la que se llama al método, con la cadena "s", hasta que la cadena tiene la longitud "l" especificada. Si no se manda "s", la cadena se rellena con espacios en blanco. |
| raw`plantilla literal` | Método estático que devuelve un String, con los elementos ${} de la plantilla evaluados, pero sin evaluar las secuencias de escape, por ejemplo, \n es devuelto como "\n" (no evaluado como un salto de línea). |
| repeat(n) | Devuelve una nueva cadena, con la cadena desde la que se llama al método repetida "n" veces. |
| replace(er, cr) | Devuelve una nueva cadena con la o las coincidencias de la expresión regular "er", reemplazadas por la cadena de reemplazo "cr". La cadena "cr" puede ser una función que devuelve la cadena de reemplazo. Para reemplazar todas las coincidencias, la expresión regular debe incluir el modificador global "g". |
| replaceAll(er, cr) | Devuelve una nueva cadena con todas las coincidencias de la expresión regular "er", reemplazadas por la cadena de reemplazo "cr". La cadena "cr" puede ser una función que devuelve la cadena de reemplazo. |
| search(s1) | Devuelve el índice (la posición) de la parte de la cadena, que coincide con la cadena (o expresión regular) "s1". |
| slice(i, j) | Devuelve una nueva cadena con los caracteres que existen entre la cadena "i" y "j-1" (o hasta último carácter si no se manda "j"). Si "i" es negativo, devuelve ese número de caracteres del final del texto. |
| split(s1) | Divide la cadena en todos los lugares que coinciden con la cadena (o expresión regular) "s1", devolviendo un vector con las cadenas resultantes de esa división. |
| startsWith(s [, i]) | Devuelve true, si la cadena desde la cual se llama al método comienza con la cadena "s". Opcionalmente puede recibir el índice "i" a partir del cual hará la comparación (por defecto 0). |
| substr(i, n) | Devuelve una nueva cadena con los "n" caracteres que se encuentran a partir de la posición "i" (o todos los caracteres a partir de "i" si se omite "n"). |
| substring(i, j) | Devuelve una nueva cadena con los caracteres desde la posición "i", hasta la posición "j-1" (o todos los caracteres a partir de "i" si se omite "j"). |
| toLocaleLowerCase([l]) | Devuelve una nueva cadena, con los caracteres de la cadena desde la cual se llama al método, en minúsculas, empleando el código local por defecto o el código local recibido en "l". |
| toLocaleUpperCase([l]) | Devuelve una nueva cadena, con los caracteres de la cadena desde la cual se llama al método, en mayúsculas, empleando el código local por defecto o el código local recibido en "l". |
| toLowerCase() | Devuelve una nueva cadena, con los caracteres de la cadena desde la cual se llama al método, en minúsculas. |
| toUpperCase() | Devuelve una nueva cadena, con los caracteres de la cadena desde la cual se llama al método, en mayúsculas. |
| toWellFormed() | Devuelve una nueva cadena, con la cadena desde la que se llama al método, pero con todos sus códigos solitarios reemplazados por el carácter U+FFFD, lo que evita errores con métodos, como encodeURI, que esperan cadenas bien formadas. |
| trim() | Devuelve una nueva cadena con los caracteres de la cadena desde la cual se llama al método, pero sin espacios en blanco ni al principio, ni al final. |
| trimEnd()/trimRight() | Devuelve una nueva cadena con los caracteres de la cadena original, pero sin espacios en blanco al final de la misma. Esta función puede ser llamada tanto con trimEnd, como con trimRight. |
| trimStart()/trimLeft() | Devuelve una nueva cadena con los caracteres de la cadena original, pero sin espacios en blanco al principio de la misma. Esta función puede ser llamada tanto con trimStart, como con trimLeft. |
| valueOf() | Devuelve el valor primitivo de un objeto de tipo String (devuelve la cadena de caracteres en sí). |
Observe que en esta lista existen algunos métodos estáticos: fromCharCode, fromCodePoint y raw. Como se recordará, los métodos estáticos son llamados desde la clase constructora, no desde una instancia u objeto, por lo tanto, estos métodos deben ser llamados desde la clase String.
Las cadenas de caracteres son, en realidad, vectores especializados en el manejo de caracteres. Por esa razón, en lugar de emplear el método charAt o el método at, para recuperar un carácter de la cadena, se puede emplear también la notación de corchetes, empleando el índice del carácter. No obstante, si la cadena tiene caracteres compuestos, como es el caso de algunos emojis y caracteres asiáticos que ocupan dos posiciones (porque están conformados por 2 caracteres), dichos caracteres no pueden ser recuperados ni con el índice ni con charAt, sino que se deben emplear los métodos fromCodePoint y codePointAt (métodos que hacen avanzar el índice dos posiciones).
Si sólo se trabaja con alfabetos occidentales (como el nuestro), es seguro emplear tanto los índices como los métodos charAt y at, así dada la siguiente cadena:
Los caracteres ubicados en las posiciones 4, 21 y 42, se puede obtener con cualquiera de las siguientes instrucciones:
Varios de los métodos, como match, search, replace y split, son de mayor utilidad cuando se trabaja con expresiones regulares, como se verá en el siguiente capítulo.
Además de estos métodos y como ya se vio en los capítulos previos, los objetos de tipo String y todos los objetos JavaScript en general, cuentan con el método toString, que devuelve la cadena que representa al objeto. En el caso de las cadenas es su valor primitivo (el texto en sí). Este método es llamado automáticamente, por Javascript, para mostrar el texto que representa al objeto, por esa razón, cuando se crea una nueva clase, generalmente es necesario sobrecribir su método toString, para que devuelva una cadena representativa y/o de utilidad práctica.
El quebrado invertido (\) seguido de otro carácter, se conoce como una secuencia de escape y representa a un carácter que no tiene representación gráfica. Por ejemplo el carácter nulo (que no tiene símbolo gráfico) se representa con la secuencia de escape: \0.
Las secuencias de escape son útiles no sólo para representar caracteres que no tienen símbolos gráficos, sino también, para incluir caracteres que tienen un significado especial, como ya se ha visto previamente con el caso de las comillas:
Las secuencias de escape que se pueden emplear en JavaScript (y en la mayoría de los lenguajes de programación) son:
| Secuencia | Descripción |
|---|---|
| \0 | Representa el carácter nulo (NUL), código hexadecimal 00. |
| \b | Representa el carácter de retroceso, código hexadecimal 08. |
| \t | Representa el carácter de tabulación horizontal, código hexadecimal 09 |
| \n | Representa el carácter de salto de línea, código hexadecimal 0A. |
| \v | Representa el carácter de tabulación vertical, código hexadecimal 0B. |
| \f | Representa el carácter de alimentación de página, código hexadecimal 0C. |
| \r | Representa el carácter de retorno de carro, código hexadecimal 0D. |
| \" | Comillas, código hexadecimal 22. |
| \' | Apóstrofo, código hexadecimal 27. |
| \\ | Quebrado invertido, código hexadecimal 5C. |
| \xXX | Representa el carácter, cuyo código hexadecimal de dos dígitos, es igual a "XX", por ejemplo \x67 representa a la letra "g". |
| \uXXXX | Representa el carácter unicode, cuyo código hexadecimal de cuatro dígitos, es igual a "XXXX", por ejemplo \u006e representa al carácter "n". | \u{X}...\u{XXXXXX} | Representa el carácter unicode, con un código hexadecimal de entre 1 hasta 6 dígitos, por ejemplo \u{2FB9} representa al carácter "⾹". |
Por ejemplo, en la siguiente instrucción, se emplean saltos de línes (\n) y tabuladores (\t) para mostrar los nombres y apellidos de una persona en dos líneas en forma tabular:
Y en la siguiente instrucción se emplean códigos hexadecimales para mostrar algunos caracteres griegos:
Mientras que en la siguiente se muestran algunos emojis:
Observe que se emplea la forma "\u{XXXXX}" porque ahora los códigos hexadecimales tienen más de 4 caracteres.
El proceso contrario, es decir obtener el código de un carácter se logra con el método codePointAt(). Por ejemplo, copiando el anterior resultado en la siguiente instrucción, se obtienen los códigos del primer y último emoji, con:
Note que el código está en formato decimal (no hexadecimal), además, para obtener el código del último caracter (el séptimo carácter) se multiplica su posición (la posición 7) por 2 (porque estos son caracteres compuestos que requieren 2 bytes).
Para convertir el resultado a format hexadecimal, se emplea el método toString al que se le manda la base a la cual se quiere convertir, en este caso 16 (porque la base es hexadecimal):
Para obtener todos los códigos a la vez, se puede crear un array con los caracteres de la matriz (Array.from) y emplear el método forEach para obtener, convertir e imprimir cada uno de los caracteres:
Cree la variable s1 con el texto "Todos los navegadores actuales soportan Javascript".
Cree la variable s2 con 11 caracteres de s1 a partir del décimo primer carácter.
Sin embargo, debido a que el método substr ha sido puesto en la lista de métodos obsoletos, es conveniente resolver este tipo de problemas con otros métodos. Así, empleando los métodos substring y slice, el problema puede ser resuelto con cualquiera de las siguientes instrucciones:
Cree la variable s3 con los caracteres del vigésimo tercero al vigésimo noveno de s1. Este problema puede ser resuelto empleando los métodos substring y slice:
Obtenga la posición (el índice) donde aparece por primera vez la cadena s2 en la cadena s1.
Obtenga la posición donde aparece por última vez la letra "a" en la cadena s1.
Obtenga el cuarto carácter de la cadena s3. Este problema puede ser resuelto con los métodos charAt, at y con la notación de corchetes:
Obtenga el código del último carácter de s1. Este problema puede ser resuelto con una combinación de los métodos at, slice y la propiedad length, para obtener el último carácter de la cadena y charCodeAt o codePointAt, para obtener el código:
También se podría emplear el método substr, pero como se dijo, al estar en la lísta de métodos obsoletos, se debe evitar su uso. Observe que s1.at(-1) y s1.slice(-1), obtienen el último carácter de la cadena "s1" (el carácter "t") y que s1.length-1, obtiene el último índice de la cadena (el número de caracteres de la cadena menos 1).
Obtenga el carácter correspondiente al código 74. Este problema puede ser resuelto con los métodos fromCharCode y fromCodePoint:
Cree la variable s1 con el texto "Se pueden añadir y/o modificar métodos mediante la propiedad prototype del constructor.";
Encuentre la posición en la que aparece, por primera vez, la cadena "métodos" dentro de la cadena s1. Este problema puede ser resuelto empleando los métodos indexOf y search:
Cree la variable s2 con la primera palabra de la cadena "s1", en minúsculas. Para obtener la primera palabra, se debe ubicar la posición donde aparece por primera vez un espacio en blanco (" "), lo que se consigue con el método indexOf o search, entonces con substring o slice, se copia la cadena que existe entre 0 y esa posición. Finalmente, la cadena se convierte a minúsculas con el método toLowerCase (también se puede emplear el método toLocaleLowerCase, pero en este caso no tiene mucho sentido, porque, toLowerCase, trabaja por defecto con la configuración local del dispositivo).
Cree la variable s3, con la última palabra de la cadena s1, en mayúsculas. En este caso, en lugar de ubicar el primer espacio en blanco, se ubica el último, lo que se consigue con lastIndexOf, entonces desde esa posición más uno (porque el espacio no es parte de la palabra), se copia la cadena con substring o slice. Para convertir la cadena a mayúsculas se emplea el método toUpperCase (aunque se puede emplear, igualmente, el método toLocaleUpperCase):
Se podría emplear igualmente search, pero en ese caso se tendría que emplear una expresión regular, las cuales serán estudiadas más adelante
Cree la variable s4, con el texto de s1, pero reemplazando la cadena "la propiedad" por la cadena "el atributo". En este caso, el método indicado para resolver el problema es replace:
Cree la variable s5 a partir de las cadenas s2 y s3 separándolas con un espacio en blanco. Este problema puede ser resuelto con el método concat, con una plantilla literal y el operador de concatenación +:
Cree un vector con las subcadenas de la cadena s1, que están entre los espacios en blanco.
Cree la variable s con el texto "Todo debe ser hecho tan simple como sea posible, pero no más simple."
Determine si la cadena "s" comienza con la cadena "Todos " o "Todo " y si termina con la cadena "simple" o "simple.". Para resolver este problema se emplea el método startsWith, para determinar si "s" comienza (true) o no (false) con las cadenas dadas y endsWith, para determinar si termina (true) o no (false) con las cadenas dadas:
Como se puede ver, el método startsWith nos informa que la cadena comienza con "Todo " y el método endsWith, nos informa que la cadena termina con "simple."
Cree una nueva cadena, rellenando el principio de la cadena "s" con caracteres "#", de manera que la longitud total de la cadena sea de 75 caracteres. Para resolver este caso se emplea el método padStart:
Cree una nueva cadena, rellenando el final de la cadena "s" con caracteres "$", de manera que la longitud total de la cadena sea de 80 caracteres. Para resolver este caso se emplea el método padEnd:
Cree las cadenas "s1", "s2" y "s3", rellenando el principio de la cadena "s" con espacios en blanco hasta una longitud total de 77 caracteres (s1), rellenando el final de la cadena "s" con espacios hasta una longitud total de 81 caracteres y rellenando, con espacios en blanco, el principio y el final de la cadena "s" hasta una longitud de 80 y 85 caracteres. En este caso se emplean, igualmente, los métodos padStart y padEnd, excepto que ahora no se manda el carácter de relleno, porque el carácter por defecto es el espacio en blanco:
Obtenga nuevas cadenas, eliminando los espacios en blanco al principio de la cadena "s1", los espacios en blanco al final de la cadena "s2" y los espacios en blanco al principio y al final de la cadena "s3". Para eliminar los espacios en blanco, al principio de la cadena, se emplean los métodos trimStart o trimLeft; para eliminar los espacios al final trimEnd o trimRight y para eliminar los espacios al principio y al final trim:
Cree la cadena "s4" repitiendo 5 veces la cadena "JavaScript". Para crear una cadena, repitiendo "n" veces una cadena dada, se emplea el método repeat:
Cree la cadena "s5" con el texto "Nunca pienso \ten el futuro. \nLlega lo \tsuficientemente pronto.", pero de manera que las secuencias de escape \t (tabulación) y \n (nueva línea) no sean interpretadas como tales, sino como caracteres normales. Para que las secuencias de escape no sean interpretadas como tales, se emplea el método estático String.raw:
Con localeCompare determine si la cadena "opción" debe ir antes de (negativo), después de (positivo) o si es igual a (cero) la cadena "opcion"; igualmente si la cadena "hola" debe ir antes, después o es igual a "Hola" y si la cadena "JavaScript" debe ir antes, después o es igual a "JavaScript":
Observe que en el primer caso, de acuerdo a localeCompare "opción" debe ir después de "opcion" (el resultado es positivo); en el segundo caso "hola" debe ir antes de "Hola" (el resultado es negativo) orden que difiere del orden ASCII estándar (donde "h" está después de "H") y en el tercer caso, como las dos cadenas son iguales, localeCompare devuelve 0.