Skip to content

6. Cadenas

Las cadenas JavaScript son muy similares a las de PHP.

Image

6.1. script [str-01]

Lo primero que hay que entender es que una vez creada una cadena, ya no se puede modificar. Hay muchos métodos disponibles para crear una nueva cadena a partir de la cadena original, pero la cadena original no se modifica. Además, una cadena puede ser de dos tipos:

  • [cadena] cuando se inicializa con un literal de cadena;
  • [objeto] cuando se crea como una instancia de la [Cadena] clase;

1. 'use strict';
2. 
3. // strings are read-only (they cannot be modified)
4. 
5. // a string
6. const string1 = "abcd ";
7. // type
8. console.log("typeof(string1)=", typeof(string1));
9. // character #2
10. console.log("string1[2]=", string1[2]);
11. // causes an error
12. string1[2] = "0";

Ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Temp\19-09-01\javascript\strings\str-01.js"
2. typeof(string1) = string
3. string1[2] = c
4. c:\Temp\19-09-01\javascript\strings\str-01.js:1
5. TypeError: Cannot assign to read-only property '2' of string 'abcd'
6. at Object.<anonymous> (c:\Temp\19-09-01\javascript\strings\str-01.js:12:12)
7. at Generator.next (<anonymous>)

6.2. script [str-02]

Este script demuestra que una cadena puede construirse de dos formas.


1. 'use strict';
2. 
3. // Strings can be of two types
4. 
5. // a literal string
6. const string1 = "abcd ";
7. // type
8. console.log("typeof(string1)=", typeof(string1));
9. // String instance
10. const string2 = new String("xyzt");
11. // type
12. console.log("typeof(string2)=", typeof(string2));
13. // alternative syntax (without `new`) – type [string] and not [object]
14. const string3 = String("12 34");
15. // type
16. console.log("typeof(string3)=", typeof(string3));
17. // The [string] type and the [object] type offer the same methods, those of the String class
18. console.log("string1.length=", string1.length);
19. console.log("string2.length=", string2.length);

Comentarios

  • línea 6: el método estándar para definir una cadena. [cadena1] será del tipo [cadena];
  • línea 10: se puede construir una cadena utilizando el constructor [String] clase. [cadena2] será de tipo [objeto];

Ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\strings\str-02.js"
2. typeof(string1) = string
3. typeof(string2) = object
4. typeof(string3) = string
5. string1.length = 5
6. string2.length = 4

El [cadena] tipo se beneficia de los métodos de la [Cadena] clase.

6.3. script [str-03]

Este script muestra una cadena específica con interpolación variable.


1. 'use strict';
2. 
3. // string
4. const string = "Introduction to JavaScript through examples";
5. // string with variable interpolation
6. const str = `[${string}].substr(3, 2)=` + string.substr(3, 2)
7. console.log(str);

Comentarios

  • línea 6: es posible tener cadenas que contengan expresiones ${variable} que son reemplazadas por el valor de la variable. Esto sigue la misma lógica que las variables $ en cadenas PHP. Tenga en cuenta la sintaxis de una cadena de este tipo: se encierra en backticks (AltGr-7 en un teclado francés);

Ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Temp\19-09-01\javascript\strings\tempCodeRunnerFile.js"
2. [Introduction to JavaScript by Example].substr(3, 2)=ro

6.4. script [str-04]

La cadena con interpolación de variables sigue siendo insuficiente. No es posible sustituir una expresión por la variable en la expresión ${variable}. Para quienes hayan programado en C, no hay nada como las [printf, sprintf] funciones para escribir o construir cadenas con formato. Cientos de desarrolladores han creado miles de paquetes JavaScript, formando un vasto ecosistema. Cuando se tiene una necesidad que JavaScript no satisface de forma nativa, es el momento de buscar un paquete que la satisfaga. Para ello, utilizamos el gestor de paquetes [npm]. Tiene una [search] opción que permite buscar una cadena dentro de las descripciones de los paquetes. [npm] devuelve una lista de paquetes que coinciden con la búsqueda. Por tanto, buscaremos la cadena [sprintf] en las descripciones de los paquetes:

Image

  • en la columna [4], las palabras clave de los paquetes en la columna [3];
  • en la columna [5], las descripciones de los paquetes en la columna [3];

El siguiente paso es ir a la [npm] página web, [https://www.npmjs.com/], y leer las descripciones de los paquetes:

Image

En [3], revisamos la lista de paquetes y seleccionamos uno.

Image

En la descripción del paquete, encontrarás instrucciones para instalarlo y utilizarlo:

Image

Instalamos el [sprintf-js] paquete en un [VSCode] terminal:

Image

Esta instalación modificará el [package.json] archivo ubicado en la raíz del [javascript] carpeta [2]:

Image

Como se muestra arriba, el paquete se ha instalado en [dependencies], es decir, los paquetes necesarios para ejecutar el proyecto. Recuerda que los paquetes necesarios sólo durante el desarrollo del proyecto se colocan en [devDependencies]. No se utilizan durante el tiempo de ejecución. Esta distinción es importante cuando se crea la versión final del proyecto para su despliegue en producción. Hay herramientas disponibles para:

  • combina todos los archivos JavaScript necesarios para la ejecución en un único archivo. Los paquetes en [devDependencias] por lo tanto, no se incluyen en este archivo final;
  • minificarlo, es decir, reducir su tamaño al máximo. Para ello, por ejemplo, se eliminan todos los comentarios;
  • "ofuscar" el código para que sea difícil de entender. Por ejemplo, las variables tasa, salario e impuesto se sustituirán por las variables a, b y c;
  • Realizar otras optimizaciones;

Esta optimización del archivo final de un proyecto JavaScript se utiliza en programación web. Una aplicación web puede depender de un gran número de archivos JavaScript. La carga de estos archivos en un navegador puede ralentizar la visualización de la primera página de la aplicación. La optimización descrita anteriormente pretende mejorar este tiempo de carga. Si los usuarios consideran que el tiempo de carga es demasiado largo, la aplicación no se utilizará.

Ahora que tenemos el [sprintf-js] paquete, tenemos que usarlo. Este es el [str-04] script:


1. 'use strict';
2. // use an external package to access the sprintf function
3. import { sprintf } from 'sprintf-js';
4. // string
5. const string = "Introduction to JavaScript by Example";
6. // method
7. console.log(sprintf("[%s].substr(3,2)=[%s]", string, string.substr(3, 2)));

Con ECMAScript 6, utilizamos la [import] palabra clave para importar un objeto exportado por un paquete. Para saber qué exporta el paquete, puedes mirar su código:

Image

  • en [1], haga clic con el botón derecho del ratón en el paquete importado;
  • en [2], queremos ver su definición;
  • en [3-4], vemos que el paquete exporta una función llamada [sprintf];

La [sprintf] función del [sprintf-js] paquete se importa mediante la siguiente sentencia:


import { sprintf } from 'sprintf-js';

El código completo:


1. 'use strict';
2. // Using an external package to access the sprintf function
3. import { sprintf } from 'sprintf-js';
4. // string
5. const string = "Introduction to JavaScript through examples";
6. // method
7. console.log(sprintf("[%s].substr(3,2)=[%s]", string, string.substr(3, 2)));

produce los siguientes resultados:


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\strings\str-04.js"
2. c:\Temp\19-09-01\javascript\strings\str-04.js:3
3. import { sprintf } from 'sprintf-js';
4. ^
5. 
6. SyntaxError: Unexpected token {
7. at new Script (vm.js:79:7)
8. at createScript (vm.js:251:10)
9. at Object.runInThisContext (vm.js:303:10)
10. at Module._compile (internal/modules/cjs/loader.js:657:28)

Línea 3: La declaración [import] no se reconoce. Esto se debe a que la versión 10.15.1 de [node.js] utilizada en este curso (septiembre de 2019) aún no admite el estándar ECMAScript para importar paquetes llamados módulos. En 2019, [node.js] soporta un estándar de módulos llamado CommonJS. La integración de módulos ECMAScript por parte de [node.js] está prevista para 2020. Una vez más, los desarrolladores han dado un paso adelante y han creado paquetes que permiten el uso de módulos ES6 con [node.js] ahora mismo (2019).

Utilizaremos un paquete llamado [esm] (Módulos ECMAScript). Lo instalamos en un terminal para el [javascript] proyecto:

Image

En [4], podemos ver que al instalar el [esm] paquete [1-3] se ha modificado el [javascript/paquete.json] archivo.

Aún no hemos terminado. Para que el [esm] módulo sea utilizado por [node.js], necesitamos ejecutarlo con el [-r esm] argumento.

Pues modificamos la configuración del [Code Runner] extensión en [VSCode]:

Image

Image

En [11], añadimos el [-r esm] argumento y guardamos (Ctrl-S) la configuración.

Ahora podemos ejecutar el [str-04] script:


1. 'use strict';
2. // use an external package to access the sprintf function
3. import { sprintf } from 'sprintf-js';
4. // string
5. const string = "Introduction to JavaScript by Example";
6. // substr method
7. console.log(sprintf("[%s].substr(3,2)=[%s]", string, string.substr(3, 2)));

Image

6.5. script [str-05]

Esto es lo que dice la documentación sobre la [sprintf] función:

Los marcadores de posición de la cadena de formato están marcados con % y van seguidos de uno o varios de estos elementos, en este orden:

  • Un número opcional seguido del signo $ que selecciona qué índice de argumento utilizar para el valor. Si no se especifica, los argumentos se colocarán en el mismo orden que los marcadores de posición en la cadena de entrada.
  • Un signo + opcional que obliga a que el resultado vaya precedido de un signo más o menos para valores numéricos. Por defecto, sólo se utiliza el signo - para los números negativos.
  • Especificador de relleno opcional que especifica qué carácter utilizar para el relleno (si se especifica). Los valores posibles son 0 o cualquier otro carácter precedido por ' (comilla simple). El valor predeterminado es rellenar con espacios.
  • Un signo - opcional que hace que sprintf alinee a la izquierda el resultado de este marcador de posición. Por defecto, el resultado se alinea a la derecha.
  • Un número opcional que especifica el número de caracteres que debe contener el resultado. Si el valor a devolver es más corto que este número, el resultado se rellenará. Cuando se utiliza con el especificador de tipo j (JSON), la longitud de relleno especifica el tamaño de tabulación utilizado para la sangría.
  • Un modificador de precisión opcional, consistente en un . (punto) seguido de un número, que especifica cuántos dígitos deben mostrarse para los números en coma flotante. Cuando se utiliza con el especificador de tipo g, especifica el número de dígitos significativos. Cuando se utiliza en una cadena, hace que el resultado se trunque.
  • Un especificador de tipo que puede ser cualquiera de:
    • % - produce un carácter % literal
    • b - devuelve un entero como número binario
    • c - devuelve un entero como el carácter con ese valor ASCII
    • d o i - devuelve un entero como número decimal con signo
    • e - devuelve un flotador utilizando notación científica
    • u - devuelve un entero como número decimal sin signo
    • f - devuelve un flotador tal cual; véanse las notas sobre precisión más arriba
    • g - devuelve un flotador tal cual; véanse las notas sobre precisión más arriba
    • o - devuelve un entero como número octal
    • s - devuelve una cadena tal cual
    • t - devuelve verdadero o falso
    • T - devuelve el tipo del argumento1
    • v - devuelve el valor primitivo del argumento especificado
    • x - devuelve un entero como número hexadecimal (minúsculas)
    • X - devuelve un entero como número hexadecimal (mayúsculas)
    • j - devuelve un objeto o matriz JavaScript como cadena codificada en JSON

El script [script-05] implementa algunos de estos formatos:


1. 'use strict';
2. // using an external package to access the sprintf function
3. import { sprintf } from 'sprintf-js';
4. // string
5. const string = "JavaScript";
6. // strings
7. console.log(sprintf("[%s, %%s]=>[%s]", string, string));
8. console.log(sprintf("[%s, %%20s]=>[%20s]", string, string));
9. console.log(sprintf("[%s, %%-20s]=>[%-20s]", string, string));
10. // integers
11. console.log(sprintf("[%d, %%d]=>[%d]", 10, 10));
12. console.log(sprintf("[%d, %%4d]=>[%4d]", 10, 10));
13. console.log(sprintf("[%d, %%-4d]=>[%-4d]", 10, 10));
14. console.log(sprintf("[%d, %%04d]=>[%04d]", 10, 10));
15. // real numbers
16. console.log(sprintf("[%f, %%f]=>[%f]", -10.5, -10.5));
17. console.log(sprintf("[%f, %%10.2f]=>[%10.2f]", -10.5, -10.5));
18. console.log(sprintf("[%f, %%-10.2f]=>[%-10.2f]", -10.5, -10.5));
19. console.log(sprintf("[%f, %%010.3f]=>[%010.3f]", -10.5, -10.5));
20. // json
21. console.log(sprintf("person (%%j)=%j", { name: "mathieu", age: 34 }));
22. // type
23. console.log(sprintf("person type (%%T)=%T", { name: "mathieu", age: 34 }));
24. // boolean
25. console.log(sprintf("boolean (%%t)=%t", 4 === 4));

Ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\strings\str-05.js"
2. [Javascript, %s]=>[Javascript]
3. [Javascript, %20s]=>[ Javascript]
4. [Javascript, %-20s]=>[Javascript ]
5. [10, %d]=>[10]
6. [10, %4d]=>[ 10]
7. [10, %-4d]=>[10 ]
8. [10, %04d]=>[0010]
9. [-10.5, %f]=>[-10.5]
10. [-10.5, %10.2f]=>[ -10.50]
11. [-10.5, %-10.2f]=>[-10.50 ]
12. [-10.5, %010.3f]=>[-00010.500]
13. person (%j)={"name":"mathieu","age":34}
14. person type (%T)=object
15. boolean (%t)=true

6.6. script [str-06]

El [str-06] script demuestra algunos métodos de la [String] clase que también se pueden utilizar en el [string] tipo:


1. 'use strict';
2. // using an external package to access the sprintf function
3. import { sprintf } from 'sprintf-js';
4. // string
5. const string = "  Introduction to JavaScript ";
6. // some methods
7. // substr(10,2): 2 characters starting from position 10
8. console.log(sprintf("[%s].substr(10,2)=[%s]", string, string.substr(10, 2)));
9. // trim: removes whitespace from the beginning and end of the string (whitespace = \b \t \r \n \f)
10. console.log(sprintf("[%s].trim()=[%s]", string, string.trim()));
11. // toLowerCase: converts to lowercase
12. console.log(sprintf("[%s].toLowerCase=[%s]", string, string.toLowerCase()));
13. // toUpperCase: convert to uppercase
14. console.log(sprintf("[%s].toUpperCase=[%s]", string, string.toUpperCase()));
15. // indexOf: position of a substring within the string, -1 if the substring does not exist
16. console.log(sprintf("[%s].indexOf('Java')=[%s]", string, string.indexOf('Java')));
17. console.log(sprintf("[%s].trim().indexOf('abcd')=[%s]", string, string.indexOf('abcd')));
18. // includes: true if the searched string is in the string
19. console.log(sprintf("[%s].includes('Java')=[%s]", string, string.includes('Java')));
20. // length: length of the string - not a method but a property
21. console.log(sprintf("[%s].length=[%s]", string, string.length));
22. // slice (7,10): characters 7 through 9
23. console.log(sprintf("[%s].slice(7,10)=[%s]", string, string.slice(7, 10)));
24. // match: searches for an expression in the string—this expression can be a regular expression
25. // /intro/i: regular expression matching the string [intro] in uppercase or lowercase
26. // returns the found string
27. console.log(sprintf("[%s].match(/intro/i)=[%s]", string, string.match(/intro/i)));
28. // replace: replaces string1 with string2 in string
29. // replaces the first occurrence of i with x
30. console.log(sprintf("[%s].replace('i','x')=[%s]", string, string.replace('i', 'x')));
31. // replaces all occurrences of i with x
32. // /i/g is a regular expression matching all (g) occurrences of i
33. console.log(sprintf("[%s].replace(/i/g,'x')=[%s]", string, string.replace(/i/g, 'x')));
34. // split: splits the string into words separated by the split parameter
35. // returns an array of these words
36. // /\s*/: words separated by zero or more spaces
37. console.log(sprintf("[%s].split(/\\s*/)=[%s]", string, string.split(/\s*/)));
38. // /\s+/: words separated by one or more spaces
39. console.log(sprintf("[%s].split(/\\s+/)=[%s]", string, string.split(/\s+/)));

Ejecución


1. [Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\strings\str-06.js"
2. [ Introduction to JavaScript ].substr(10,2)=[ti]
3. [ Introduction to JavaScript ].trim()=[Introduction to JavaScript]
4. [ Introduction to JavaScript ].toLowerCase=[ introduction to javascript ]
5. [ Introduction to JavaScript ].toUpperCase=[ INTRODUCTION TO JAVASCRIPT ]
6. [ Introduction to JavaScript ].indexOf('Java')=[17]
7. [ Introduction to JavaScript ].trim().indexOf('abcd')=[-1]
8. [ Introduction to JavaScript ].includes('Java')=[true]
9. [ Introduction to JavaScript ].length=[28]
10. [ Introduction to JavaScript ].slice(7,10)=[duc]
11. [ Introduction to JavaScript ].match(/intro/i)=[Intro]
12. [ Introduction to JavaScript ].replace('i','x')=[ Introductxon to JavaScript ]
13. [ Introduction to JavaScript ].replace(/i/g,'x')=[ Introductxon to Javascrxpt ]
14. [ Introduction to JavaScript ].split(/\s*/)=[,I,n,t,r,o,d,u,c,t,i,o,n,à,J,a,v,a,s,c,r,i,p,t,]
15. [ Introduction to JavaScript ].split(/\s+/)=[,Introduction,to,JavaScript,]