back to top

Javascript Template Strings

Proseguiamo la nostra rubrica interamente dedicata alle nuove e potenti caratteristiche introdotte nel motore del linguaggio Javascript con la specifica ECMAScript 6, parlando di una feature particolarmente apprezzata dagli sviluppatori di tutto il mondo: i template strings.

Stringhe potenziate dove interpolare valori dinamici

In Javascript, le stringhe sono state fin dagli albori considerate un tool a funzionalità "limitata", perchè prive di quelle caratteristiche e capacità fondamentali tipiche di linguaggi come Python, Ryby o PHP. Chi ha dimestichezza con uno o più di questi linguaggi di programmazione, sa che in questi contesti le stringhe non si limitano unicamente a conternere parole o sequenze di caratteri alfanumerici, ma hanno la capacità di interpolare valori dinamici e di essere parsate dal motore dedicato.

Ad esempio, in Ruby, possiamo scrivere:

name = "Riccardo"
puts "Hello, #{name}!"

Il pattern "#{name}" verrà sostituito dinamicamente con il valore della rispettiva variabile (denominata "name") producendo l’opportuno risultato. Anche in PHP, utilizzando le stringhe attraverso le virgolette doppie, possiamo utilizzare il motore di parsing per produrre interpolazioni dinamiche, ad esempio:

<?php
$name = "riccardo";
$lastname = "degni";

echo "Hello, {$name} {$lastname}";
?>

Anche in questo caso, all’interno dell’ultimo letterale stringa, verranno sostituite le variabili "$name" e "$lastname" con i rispettivi valori, producendo l’interpolazione (nota: sia in Ruby che in PHP, dichiarare una stringa utilizzando le virgolette singole e le virgolette doppie NON è la stessa cosa. Nel primo caso il motore di parsing non verrà azionato, ed il contenuto verrà trattato come semplice sequenza di caratteri alfanumerici, mentre nel secondo caso avremo la possibilità di interpolare dinamicamente i valori, come variabili, costanti, proprietà, metodi e funzioni).

Cosa sono i template strings?

Grazie ai template strings nati con ECMAScript 6 sarà dunque fondamentalmente possibile produrre stinghe "potenziate", sulla quale sarà possibile effettuare:

  • l’interpolazione di variabili
  • le espressioni embedded
  • le stringhe multilinea senza "hacks"
  • la formattazione delle stringhe
  • il tagging delle stringhe per maggiore sicurezza HTML (escaping) e localizzazione

Invece che ampliare le vecchie caratteristiche delle stringhe dunque, ECMAScript 6 ci offre un motore completamente diverso per realizzare queste moderne funzionalità. Possiamo dunque dire che i template strings sono letterali stringa che permettono l’incorporazione di differenti espressioni.

Nota: i template strings possono essere chiamati anche utilizzando il nome più moderno, "template literals": ovvero letterale template. Le variabili in Javascript possono infatti essere comodamente prodotte attraverso i letterali, senza passare dai costruttori. Per differenziare questa tipologia di stringhe da quelle comuni, è stata agganciata anche questa terminologia.

Come utilizzare i template strings

Prima di tutto, è bene sapere che nonostante siano di fatto delle stringhe, i template strings non si costruiscono ne attraverso le virgolette singole, ne attraverso le virgolette doppie. Abbiamo bisogno di utilizzare il carattere backtick (chiamato anche "accento grave"): ` `. L’accento grave in informatica viene spesso utilizzato nella programmazione. Tuttavia, nonostante sia presente sulla tastiera inglese, su quella italiana risulta essere un carattere nascosto. Per poterlo ottenere sulla suddetta tastiera si deve agire nelle seguenti modalità:

  • in ambiente Microsoft Windows: premendo in successione i tasti "9" e "6" (del tastierino numerico) mentre si tiene premuto il tasto "Alt"
  • nei sistemi Unix-like come Linux, premendo contemporaneamente i tasti "Alt Gr" e "’".

Ad esempio, per dichiarare un template string, scriveremo:

var sayHello = `Hello World!`;

In questo esempio di base, non esiste molta differenza tra un template string ed una stringa comune. Vediamo come evidenziare invece le differenze.

Interpolazione di variabili ed espressioni

I template strings possono contenere degli appositi "segnaposto", che permettono, come abbiamo visto anche in precedenza nel caso di Ruby e PHP, di interpolare dinamicamente le variabili. Per definirli, dobbiamo includere la nostra espressione all’interno del simbolo del dollaro e delle parentesi graffe: ${expressione}. L’espressione posizionata all’interno del segnaposto viene passata ad una funzione, che di default si limita a concatenare le differenti parti all’interno della stringa finale. Ad esempio:

var name = "Riccardo";
console.log(`Ciao, ${name}!`);

// => "Ciao, Riccardo!"

Grazie al template string la variabile "name" viene interpolata nella stringa che andiamo a produrre in output, scrivendo in console "Ciao, Riccardo!".

Ma dato che abbiamo utilizzato il termine "espressioni", non siamo limitati unicamente all’interpolazione di dati statici. Possiamo invece interpolare anche espressioni dinamiche, come ad esempio delle operazioni:

var a = 10;
var b = 10;
console.log(`La somma di 10 e 10 è: ${a+b}`)

Come possiamo vedere, possiamo interpolare anche un’operazione matematica all’interno del segnaposto. Il precedente codice produce dunque "La somma di 10 e 10 è 20".

La potenza dell’interpolazione non si ferma qui! Possiamo utilizzare nelle espressioni anche chiamate di funzioni:

function myfn() { return "ciao"; }
console.log(`dico ciao: ${ciao()} !`);

In questo caso abbiamo definito una funzione denominata "myfn". All’interno del nostro segnaposto andremo a richiamarla, cosi da produrre l’interpolazione che genera l’output finale "dico ciao: ciao!". Ovviamente possiamo utilizzare l’interpolazione anche in collaborazione con gli oggetti, con proprietà (variabili appartenenti ad un’istanza) e metodi (funzioni appartenenti ad un’istanza):

var user = {name: 'Riccardo Degni'};
console.log(`Grazie per esserti registrato, ${user.name.toUpperCase()}.`);

In questo caso abbiamo un oggetto denominato "user" che contiene una proprietà "name" impostata ad un dato valore. All’interno del template string interpoliamo questa proprietà richiamando inoltre il metodo del prototipo String "toUpperCase" che andrà a rendere maiuscole tutte le lettere del suddetto valore. Otterremo cosi l’output "Grazie per esserti registrato, RICCARDO DEGNI".

Nota: se hai la necessità di introdurre il carattere "backtick"/accento grave all’interno di un template string, puoi effettuare l’escape attraverso il carattere di "backslash", come accade nelle stringhe comuni:

var astring = `\`Hello\` World!`;

In questo codice i backtick che avviluppano "Hello" sono normalmente prodotti come caratteri normali.

Stringhe multilinea

Negli anni, le stringhe multilinea hanno generato non pochi problemi agli sviluppatori front-end. Una delle soluzioni, senza l’utilizzo dei template strings, risiede nella suddivisione della stringa principale in una moltitudine di linee a cui è applicato il carattere di backslash "\" alla fine di ogni linea, come ad esempio:

var astring = "Hello \
World";

Questo procedimento, che rientra sempre nel meandro degli "hack", funziona correttamente in più o meno tutti i maggiori browser. Inoltre, è possibile utilizzare la concatenazione di stringhe per "scimmiottare" il supporto multilinea, ma questo approccio non è di sicuro tra i più eleganti:

var astring = "Hello " + 
"World";

Un’altra possibilità per raggiungere il medesimo risultato è quella dettata dal metodo "join" della classe Array, applicabile ad un array di stringhe, che verranno unificate attaverso il carattere di newline ("\n"):

var text = [
  'hello',
  'riccardo',
  'degni'
].join('\n')

Con l’avvento dei template strings, non abbiamo più la necessità di utilizzare caratteri di newline, hacks, o concatenzaione. Ogni nuova linea viene trattata come una nuova linea, cosi come appare nel codice (un pò come accade nella notazione "heredoc" di PHP), ad esempio:

console.log(`stringa sulla linea 1
stringa sulla linea 2`);

Questa riga di codice produrrà un otutput suddiviso in due righe:
"stringa sulla linea 1
stringa sulla linea 2"

Nota: tutti gli spazi inclusi nel template string vengono considerati parti della stringa.

Innestare i template

Ci sono dei casi (assolutamente comuni) in cui risulta più conveniente e leggibile innestare più operazioni all’interno di un template string, al posto di spezzare il codice in più segmenti differenti. Ad esempio, possiamo pensare al caso in cui dobbiamo utilizzare un operatore ternario, che non fa altro che simulare una condizione "if/else" ed eseguire un blocco di codice al posto di un altro in base alla condizione posta all’inizio. Prendiamo in considerazione una situazione in cui abbiamo l’ocorrenza di stampare dei valori dinamici per un attributo CSS "class" in base a determinate condizioni, come potrebbero essere il controllo della sezione corrente e la pressione del mouse sopra un elemento. Utilizzando due operatori ternari concatenati, prima di ECMAScript 6, avremmo scritto:

var classString = 'defaultlink';
classString += (isCurrentSection() ?
'' : (menulink.isClicked ?
' classA' : ' classB'));

Con i template strings possiamo compattare tutto all’interno dei backtick, sia utilizzando un unico template string:

let classes = `header ${ isCurrentSection() ? '' :
(menulink.isClicked ? 'classA' : 'classB') }`;

sia innestando un template string all’interno di un altro template string:

let classes = `header ${ isCurrentSection() ? '' :
`${menulink.isClicked ? 'classA' : 'classB'}` }`;

All’interno dell’ambiente determinato dai backtick è possibile infatti innestare altri backtick, utilizzandoli all’interno del segnaposto (contrassegnato da "${}") a sua volta contenuto nel template string esterno. Attraverso l’innestazione dei template strings le possibilità sono pressochè infinite, tuttavia occorre fare attenzione ai singoli risultati prodotti dai singoli template strings innestati, per non generare errori o imprecisioni.

Tagged templates

Un utilizzo più avanzato dei template string ci introduce ad un’ulteriore funzionalità ECMAScript 6: i cosiddetti "tagged templates". In sostanza, possiamo decidere di elaborate un template string attraverso una funzione personalizzata, che non si limita alla sostituzione e concatenazione di valori come accade nell’interpolazione di default. Questa funzionalità si attiva quando posizioniamo un template string dopo il nome di una funzione: la chiamata alla funzione indicata viene prodotta in maniera similare a come vengono impostati i parametri (nella lista di valori posizionati tra parentesi tonde).

Ad esempio, la seguente chiamata alla funzione denominata "tagFunction":

tagFunction`Hello ${firstName} ${lastName}!`

è molto simile (nella versione più esterna, equivalente) alla seguente chiamata:

tagFunction(['Hello ', ' ', '!'], firstName, lastName)

Il nome della funzione (che nel primo caso può essere definita come "funzione tag") è posizionato in modo da precedente il template string. Questa funzione riceve due tipi di dati:

  • un array di stringhe come primo parametro, contenente tutti i segmenti contenuti nel template string utilizzato
  • X argomenti direttamente correlati all’espressione passata nel template string. Il loro numero dipende dunque dal contesto, e non è statico

La funzione può restituire la stringa appositamente elaborata, oppure qualsiasi altro valore. Vediamo un esempio completo:

var user = {
  'name': 'Riccardo',
  'country': 'Italy'
};

function fntag(strings, name, country) {
  var str = 'è ';
  switch(country) {
    case 'Italy':
      str += 'italiano';
      break;

    case 'England':
      str += 'inglese';
      break;
  }

  return `Dunque, ${user.name} ${str}`;
}

var output = fntag`${ user.name } ${ user.country }`;

console.log(output);

Prima di tutto, creiamo un oggetto denominato "user" con due proprietà: "name" e "nationality". Noi vogliamo che quando parsiamo un oggetto di questo tipo attraverso la funzione di nostra creazione chiamata "fntag" venga generata una particolare stringa, avente il seguente formato: "Dunque, X è Y", dove "X" è il nome dell’utente e "Y" è il nome della sua nazionalità.

Per fare questo passiamo alla funzione tag tre argomenti: l’array di stringhe più due argomenti aggiuntivi che rappresentano i valori da elaborare. Se infine richiamiamo la funzione con il template string, otteniamo l’output desiderato, basato sui valori che utilizziamo in chiamata, ovvero: "Dunque, Riccardo è italiano".

Nello stesso esempio, possiamo lavorare con l’array di strighe, che contiene tutti i segmenti del template string suddivisi in un array (il primo argomento della funzione):

var user = {
  'name': 'Riccardo',
  'country': 'Italy'
};

function fntag(strings, name, country) {
  var str = 'è ';
  switch(country) {
    case 'Italy':
      str += 'italiano';
      break;

    case 'England':
      str += 'inglese';
      break;
  }

  return `Dunque, l'${strings[0]}${user.name} ${str}`;
}

var output = fntag`UTENTE ${ user.name } ${ user.country }`;

console.log(output);

La parola "UTENTE" presente all’interno del template string, dato che è il primo segmento dello stesso template, sarà posizionata alla posizione zero dell’array "strings", e quindi accessibile attraverso "strings[0]". Andiamo dunque ad interpolarla all’interno della stringa di restituzione, ed otterremo l’output "Dunque, l’UTENTE Riccardo è italiano". Nota: abbiamo rimosso il carattere di whitespace tra il segmento "string[0]" ed il segmento "user.name", dato che i segmenti dell’array di stringhe contengono lo spazio. Dato che i caratteri di whitespace sono parsati nei template strings, avremmo altrimenti ottenuto un doppio spazio.

Se la funzione tag restituisce un altra tipologia di valore, possiamo utilizzare quel valore per altri tipi di operazioni successive, come ad esempio il passaggio del suddetto valore sottoforma di parametro per un’ulteriore funzione.

Conclusioni

I template strings sono un’aggiunta davvero rivoluzionaria nell’ambito del linguaggio Javascript, forse ancora di più rispetto alle funzionalità che abbiamo analizzato nei precedenti tutorial, le classi e le arrow functions. Mentre queste ultime vanno ad aggiungere funzionalità nuove, che si basano però sul motore delle precedenti funzionalità, permettendo di migliorare la sintassi generale del codice oppure di aggiungere singole feature che prima non erano di fatto possibili, nel caso dei template strings arriva una caratteristica del tutto NUOVA, che di fatto rappresenta un’aggiunta ed un’evoluzione rispetto alle precedenti specifiche ECMAScript. Grazie ai template strings sono infatti ora disponibili funzionalità che non erano replicabili in precedenza, come l’interpolazione dinamica delle variabili e delle espressioni, ed i tagged templates. In questo modo Javascript si avvicina enormemente a linguaggi di programmazione molto apprezzati ed "evoluti", come ad esempio Ruby. Con la specifica ECMAScript 6, lo sviluppatore Javascript deve di fatto evolversi ed amalgamarsi a tutte le nuove funzionalità che sono ora presenti e disponibili, senza però snobbare i vecchi stili di programmazione, che sono sempre presenti ed utilizzati, anche per manterenere un alto grado di compatibilità con le vecchie versioni dei principali browser Web. Tuttavia, grazie ad ECMAScript 6, possiamo dire di essere ormai entrati in una nuova era, in cui il linguaggio Javascript si sta evolvendo sempre maggiormente, andando a mantenere inalterate le caratteristiche che l’hanno reso meritatamente celebre, ed introducendo un kit di funzionalità che erano richieste a gran voce da tutti gli sviluppatori del globo.

Altri contenuti interessanti

Pubblicitร 

Leggi anche...

Il file manifest.json: cos’รจ e a cosa serve

Il file manifest.json รจ un componente chiave nelle applicazioni web moderne,...

Infinite scroll, come programmarlo su AMP e su Web con Javascript

L'infinite scroll è una tecnica di design e navigazione...

Codice Fiscale: 5 javascript per la verifica e il calcolo

Il codice fiscale รจ un identificativo tributario univoco che...

Math.ceil() – Arrotondare per eccesso con Javascript

Il metodo ceil() dell'oggetto Math di Javascript è utilizzato...

Minificare Javascript: librerie e strumenti online per comprimere il sorgente JS

La minificazione è un processo abbastanza diffuso nell'implementazione delle...

Javascript: svuotare un campo input o una textarea con un click

Quando si fornisce agli utenti un modulo per l'inserimento...
Pubblicitร