Template Strings - JavaScript

Template strings, também conhecidos como literals de template, permitem a inserção de diversos valores dentro de uma string, uma técnica chamada interpolação. Para isso, as strings são delimitadas por acentos graves e o valor a ser inserido é precedido pelo símbolo $ e colocado entre chaves:

const name = "Tom";
const hello = `Hello ${name}`;
console.log(hello);     // Hello Tom

Nesse caso, o valor da constante name substitui ${name}, formando a string "Hello Tom".

De maneira similar, é possível inserir múltiplos valores numa única string:

const name = "Tom";
const age = 37;
const userInfo = `${name} is ${age} years old`;
console.log(userInfo);      // Tom is 37 years old

Também é viável adicionar propriedades de objetos mais complexos:

const tom = {
  name: "Tom",
  age: 22
}
const tomInfo = `${tom.name} is ${tom.age} years old`;
console.log(tomInfo);       // Tom is 22 years old

Além disso, é possível realizar operações matemáticas e lógicas dentro de template strings:

function sum(x, y) {
  return x + y;
}
const a = 5;
const b = 4;

const result = `${a} + ${b} = ${sum(a, b)}`;
console.log(result);    // 5 + 4 = 9

const expression = `${a} * ${b} = ${a * b}`;
console.log(expression);    // 5 * 4 = 20

No primeiro exemplo, a função sum() é chamada dentro do template, usando os valores das constantes a e b. Já no segundo exemplo, a operação de multiplicação é realizada diretamente no template.

Uso de HTML em Templates

Templates também podem incluir código HTML que será dinamicamente formado:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Programício</title>
</head>
<body>
<script>
const tom = {name: "Tom", age: 37};
const markup = `<div>
    <p><b>Name</b>: ${tom.name}</p>
    <p><b>Age</b>: ${tom.age}</p>
</div>`;

document.body.innerHTML = markup;
</script>
</body>
</html>
Template strings em JavaScript

Templates Aninhados

Vejamos outro exemplo: criando uma lista HTML a partir de elementos de um array:

<!DOCTYPE html>
  <html>
  <head>
      <meta charset="utf-8" />
      <title>Programício</title>
  </head>
  <body>
  <script>
  const people = [{name: "Tom", age: 37}, {name:"Sam", age: 41}, {name: "Bob", age: 21}];
  const markup = `<ul>
      ${people.map(person => `<li>${person.name}</li>`).join('')}
  </ul>`;
  
  document.body.innerHTML = markup;
  </script>
  </body>
  </html>
Template strings aninhados em JavaScript

Aqui, um template aninhado é utilizado, onde um template externo é definido e, dentro dele, um template dinâmico é aplicado utilizando a função map(), que executa uma ação para cada elemento do array people. Essa ação é expressa por uma função lambda que cria um template de string para cada pessoa.

Funções de Tag e Passagem de Template Strings para uma Função

O JavaScript permite passar uma template string para uma função, não apenas como uma string comum, mas também todos os seus fragmentos dinamicamente calculados como parâmetros separados. Para isso, são utilizadas as funções de tag. Essa capacidade pode ser usada, por exemplo, para pré-processar templates e seus valores. Vejamos o exemplo a seguir:

const person = "Tom";

function check(parts, name) {
    console.log('parts: ', parts);
    console.log('name: ', name);
    return parts[0] + name + parts[1];
}
const checkedTemplate = check`Person: ${person}.`;
console.log('checkedTemplate: ', checkedTemplate);

A função de tag check() definida acima possui dois parâmetros: parts e name:

function check(parts, name) {
  console.log('parts: ', parts);
  console.log('name: ', name);
  return parts[0] + name + parts[1];
}

O parâmetro parts é um array das partes do template, dividido pelos fragmentos dinâmicos inseridos. O segundo parâmetro, name, é um fragmento dinâmico do template. Ou seja, neste caso, assumimos que a template string passada para a função check() terá apenas um fragmento dinâmico calculado. Assim, o array parts terá dois elementos: a parte estática do template, que vem antes do fragmento calculado, e a parte que vem após.

Para esclarecer sobre o que estamos falando, os elementos do array parts e o valor do parâmetro name são exibidos no console.

A função retorna parts[0] + name + parts[1], ou seja, basicamente retornamos o template formatado originalmente, sem alterações.

Observe como passamos o template para esta função:

const checkedTemplate = check`Person: ${person}.`;

O template é simplesmente especificado após o nome da função. Ou seja, a função de tag é usada como um prefixo antes do template.

Resultado da execução do programa:

parts:  [ 'Person: ', '.' ]
name:  Tom
checkedTemplate:  Person: Tom.

Como podemos ver, que os elementos do array parts são as substrings "Person: " e ".". O valor do parâmetro name é a string "Tom". É importante notar que, mesmo se após o fragmento dinâmico não houvesse mais nenhum caractere (por exemplo, Person: ${person}), o array parts ainda teria dois elementos, sendo o segundo uma string vazia.

No exemplo acima, simplesmente retornamos o mesmo conteúdo que foi formado com base no template. No entanto, podemos realizar algum processamento:

const tom = "Tom";
const admin = "Admin";

function check(parts, name) {
    if (name === "Admin") return "Usuário não identificado";
    else return parts[0] + name + parts[1];
}
let checkedTemplate1 = check`Usuário: ${tom}`;
let checkedTemplate2 = check`Usuário: ${admin}`;

console.log(checkedTemplate1);
console.log(checkedTemplate2);

Neste caso, se o valor "Admin" é passado para o template, retornamos um resultado diferente; caso contrário, retornamos o que teria sido formado com base no template.

Usuário: Tom
Usuário não identificado

Podemos processar templates com um maior número de fragmentos dinâmicos dessa forma:

const tom = {name: "Tom", age: 37};
const bob = {name: "Bob", age: 11};

function check(parts, name, age) {
    if (age > 18) return `${parts[0]}${name}. Acesso permitido`;
    else return `Para o usuário ${name} o acesso é negado. Idade ${age} não permitida`;
}
let checkedTemplate1 = check`Usuário: ${tom.name} ${tom.age}`;
let checkedTemplate2 = check`Usuário: ${bob.name} ${bob.age}`;

console.log(checkedTemplate1);
console.log(checkedTemplate2);
  

Neste último caso, o template contém dois fragmentos dinâmicos. Assim, o array parts terá três elementos.

Na função check(), dependendo do valor do segundo fragmento dinâmico (a idade do usuário), retornamos um valor ou outro.

Saída do console:

Usuário: Tom. Acesso permitido
Para o usuário Bob o acesso é negado. Idade 11 não permitida
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com