Plantillas de cadena de texto en JavaScript
Se acerca el final del año y uno, que gusta mucho de explorar las novedades en el mundo de la programación Web, no puede evitar preguntarse que novedades nos llegarán el próximo año al mundo de la programación Web. Sin embargo, el problema de las novedades en el mundo Web, es que suele ser necesario esperar un cierto periodo de tiempo antes de aventurarse a utilizar ciertas cosas en entornos en producción. En el artículo de hoy, quiero mostraros como funcionan las plantillas de cadena de texto (template literals) que fueron introducidas en las versiones ES6/ES2015 de JavaScript/ECMAScript, y publicadas en Junio de 2015 (hace apenas dos añitos y medio).
Esta nueva funcionalidad del lenguaje, esta previsto que en la nueva versión del próximo año (ES2018) reciba algunas mejoras, aunque aún queda tiempo para que estas mejoras estén completamente soportadas. De paso, aprenderemos también el funcionamiento de otras dos novedades de ES2015, concretamente, el operador spread y los parametros rest.
¿Cuál es el soporte de las plantillas de cadena de texto en los navegadores?
En este enlace de canisue, podemos ver que el soporte es bastante aceptable. Siendo la excepción el navegador obsoleto Internet Explorer, y los navegadores para móviles Opera Mini y UC Browser (este último con fuerte presencia en China).
Así que, excepto en el caso de que tengamos previsto un número importante de visitas por parte de usuarios Chinos, no es descabellado empezar a utilizar estas plantillas de cadena de texto en nuestros proyectos Web.
¿Qué nos ofrecen las plantillas de cadena de texto?
En realidad no nos ofrecen nada nuevo, pero si van a permitirnos un código mucho más limpio, ya que esta nueva característica viene a suplir dos de las carencias más importantes de JavaScript a la hora de trabajar con cadenas de texto (sobretodo, a la hora de generar código HTML); con las plantillas de cadena de texto, podremos concatenar textos y escribir en varias líneas de forma más limpia.
¿Cómo funcionan las plantillas de cadena de texto?
Normalmente para escribir una cadena de texto en JavaScript utilizamos las comillas simples o dobles. Para usar las plantillas de cadena de texto, deberemos de escribir la cadena de texto utilizando la tilde invertida o acento grave.
Para concatenar texto, dentro de una plantilla de cadena de texto podemos introducir lo que se conoce como marcador, que es una posición del texto que será reemplazada por el contenido de una expresión. Para escribir un marcador usaremos esta sintaxis: ${expresión}.
Para utilizar múltiples líneas de texto, simplemente escribiremos el texto usando múltiples líneas (así de fácil).
Si suena todo muy confuso, no os preocupéis, en los siguientes ejemplos os quedará todo mucho más claro.
// ejemplo normal de multilinea console.log("Ejemplo normal\nmultilinea."); // ejemplo con plantillas de cadena de texto console.log(`Ejemplo de multilinea con plantillas de cadena de texto.`);
Tal y como se puede observar en este primer ejemplo, tradicionalmente, en JavaScript hemos tenido que usar la secuencia de escape \n para «romper» una cadena en varias líneas. Con las plantillas de cadena de texto, tal y como se puede observar en el ejemplo, ya no es necesario. Tan solo tenemos que usar el acento grave en lugar de las comillas simples o dobles y escribir dentro el texto tal y como lo queremos.
Veamos otro ejemplo donde se puede ver mejor la utilidad de las plantillas de cadena de texto. Esta vez, además de texto multilinea, vamos a usar los marcadores de posición.
var peliculas = [ { nombre: "Avalon", anyo: "2001" }, { nombre: "The Sky Crawlers", anyo: "2008" }, { nombre: "Ghost in the Shell", anyo: "1995" }, { nombre: "Patlabor 2", anyo: "1993" } ]; var tabla = `<table border="1"> <tr> <th>Película</th> <th>Año</th> </tr>`; for (var i=0;i<peliculas.length;i++) { tabla += ` <tr> <td>${peliculas[i].nombre}</td> <td>${peliculas[i].anyo}</td> </tr>`; } tabla += ` </table>`; document.write(tabla); console.log(tabla);
Lo bonito de la forma de escribir este código, no es solo que es más claro y limpio que usando la forma clásica de concatenar strings (con el símbolo +), sino que además, el código HTML generado va a respetar los saltos de línea y los espacios que hemos utilizado. Por lo que el código generado va a ser un código muy limpio y fácil de leer, tal y como puedes observar en la consola del navegador tras ejecutar el código.
Como ya se ha comentado, dentro del marcador podemos indicar una expresión, por lo que no es necesario que sea una simple variable; podemos hacer cosas como la siguiente:
console.log(`Dos más dos es igual a ${2+2}`);
Existe la posibilidad de un uso más avanzado, pero antes es necesario que os explique otro par de las novedades que nos trajo ES2015.
El operador spread y los parametros rest
El operador spread, básicamente lo que hace es coger los elementos de un array y colocarlos separados por comas.
El ejemplo clásico se puede ver con las funciones max o min del objeto Math. Estas funciones devuelven, respectivamente, el número más alto o el número más bajo de todos aquellos números que pasemos por parámetro. Es importante destacar que no le podemos pasar directamente un array a esta función, pero con el operador spread si que podemos hacerlo. De nuevo, con un ejemplo quedará todo más claro:
// ejemplo de uso del método max console.log(Math.max(4,10,2)); // si intentamos usar un array no funciona var a = [4,10,2]; console.log(Math.max(a)); // ...a no ser que usemos el operador spread console.log(Math.max(...a));
Tal y como se puede observar en el ejemplo, el operador spread consiste en colocar tres puntos antes del array. Tiene muchos usos; veamos otro ejemplo de como copiar y concatenar arrays con el operador spread:
var a = [1,2,3]; var b = [4,5,6]; var x = a; // x no es una copia de a, es una referencia al mismo array var y = [...a]; // y será una copia de a, es otro array diferente var z = [...a, ...b]; // z nuevo array concatenando a y b
Como podéis ver, es bastante fácil. Tan solo tenéis que imaginar, que en lugar de los tres puntos y el nombre del array, tenemos todos los elemento del array separados por comas.
Los parámetros rest son muy similares, pero funcionan básicamente al revés que el operador spread. Como su nombre indica, son parámetros de una función. Con un ejemplo nos quedará más que claro.
function ejemplo(...numeros) { for (var i=0;i<numeros.length;i++) { console.log(numeros[i]); } }; ejemplo(1,2,3,4,5,6);
Tal y como se puede ver en el ejemplo, el parámetro rest se indica con tres puntos antes del nombre del parámetro. Al invocar la función, lo hacemos separando los elementos del futuro array separados por coma, pero dentro de la función, lo que obtenemos es un array. Una vez entendido el operador spread, es sencillo, ¿no?
Volvamos a las plantillas de cadena de texto
Plantillas de cadena de texto con postprocesador
Para esta funcionalidad (tagged template literals) de las plantillas de cadenas de texto, hemos de definir una función con dos parámetros. El primero es un array normal que contendrá todos los fragmentos de texto de la plantilla (un elemento del array por cada trozo de texto que hay entre los marcadores). El segundo, es un parámetro rest que contendrá los valores de cada marcador de la plantilla.
Lo mejor, como siempre, es ver un ejemplo:
function negrita(strings, ...values) { var s = ""; for (var i=0;i<strings.length;i++) { s += strings[i]; if (values[i]) { s += "<b>" + (values[i] || '') + "</b>"; } } return s; } console.log(negrita`Dos más dos es ${2+2}.`); console.log(negrita`Uno más uno es ${1+1} y dos más dos son ${2+2}.`);
El el primer console log el texto de la plantilla ha sido dividido en dos fragmentos (el que hay antes del marcador y el que hay después), así que en el array strings tendremos dos elementos. Como solo tenemos un valor (un marcador) tenemos que controlar dicha situación en el código de la función. En el segundo console log, tenemos tres fragmentos de texto entre los marcadores, y dos valores (uno por marcador).
Esta forma de trabajar nos dará total libertad de definir exactamente como se ha de construir nuestra plantilla. ¿Y para que nos puede servir esto? Pues, por ejemplo, para añadir una clase que pinte de color rojo un importe solo si el valor es negativo.
function valorNeg(strings, ...values) { var s = ""; for (var i=0;i<strings.length;i++) { s += strings[i]; if (values[i]) { if (parseFloat(values[i]) < 0) { s += "<span class='red'>" + (values[i] || '') + "</span>"; } else { s += "<b>" + (values[i] || '') + "</b>"; } } } return s; } console.log(valorNeg`Importe positivo: ${123}.`); console.log(valorNeg`Importe negativo: ${-123}.`);
¿Qué nos deparará JavaScript el próximo año con la versión ES2018?
Probablemente hasta Junio no lo sabremos con certeza, pero si tienes curiosidad, en este artículo se discuten algunas de las posibles novedades de ES2018. Salga lo que salga, desafortunadamente, tendremos que esperar otro par de años a que los navegadores incorporen dichas novedades.
Espero que el post haya sido interesante para vosotros, un saludo!