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 $
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()
a
b
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>
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>
Aqui, um template aninhado é utilizado, onde um template externo é definido e, dentro dele, um template dinâmico é aplicado utilizando a função map()
people
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()
parts
name
function check(parts, name) {
console.log('parts: ', parts);
console.log('name: ', name);
return parts[0] + name + parts[1];
}
O parâmetro parts
name
check()
parts
Para esclarecer sobre o que estamos falando, os elementos do array parts
name
A função retorna parts[0] + name + parts[1]
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
name
Person: ${person}
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
Na função check()
Saída do console:
Usuário: Tom. Acesso permitido Para o usuário Bob o acesso é negado. Idade 11 não permitida