Um caminho para compreender os literais de modelo em JavaScript

A especificação ECMAScript 2015 ( ES6 ) adicionou um novo recurso ao JavaScript - literais de modelo. Literais de modelo nos fornecem um novo mecanismo para criar valores de string... Esse mecanismo possui muitos recursos poderosos, como tornar mais fácil criar construções multilinhas e usar marcadores para incorporar resultados de expressão em strings. Além disso, há outra possibilidade aqui - literais de modelo marcados. Esta é uma forma estendida de literais de modelo. Os modelos de tag permitem criar strings usando expressões dentro de strings e funções especiais. Tudo isso expande a capacidade dos programadores de trabalhar com strings, permitindo, por exemplo, criar strings dinâmicas que podem ser URLs ou escrever funções para ajustar elementos HTML .







Neste artigo, você aprenderá sobre as diferenças entre valores de string regulares, especificados com aspas simples ou duplas, e literais de modelo. Você aprenderá sobre as diferentes maneiras de declarar strings com características diferentes, incluindo strings multilinhas e strings dinâmicas que mudam dependendo do valor de uma variável ou expressão. Você aprenderá como trabalhar com modelos de tag e ver exemplos do mundo real de seu uso.



Declarando strings



Nesta seção, relembramos como as strings são declaradas usando aspas simples ou duplas e, em seguida, veremos como o mesmo é feito ao usar literais de modelo.



Uma string JavaScript pode ser considerada uma sequência de caracteres entre aspas simples ( ' '):



const single = 'Every day is a good day when you paint.'


Outra maneira de declarar strings é usar aspas duplas ( " "):



const double = "Be so very light. Be a gentle whisper."


Em JavaScript, não há grandes diferenças entre essas strings. Em outras linguagens, o uso de aspas diferentes ao declarar strings pode significar, por exemplo, que strings de um tipo podem ser interpoladas enquanto outros não. Aqui, entendemos por "interpolação" a capacidade de calcular os valores de expressões de espaço reservado que desempenham o papel de porções dinâmicas de strings e participam da formação dos valores de string resultantes.



Quais strings usar quando declaradas com aspas simples ou duplas é em grande parte uma questão de preferência pessoal e convenções de codificação. No entanto, se uma string delimitada por um desses tipos de aspas contiver aspas do mesmo tipo, elas devem ter escape . As citações de um tipo diferente em tais strings não precisam de escape.



//     ,   
const single = '"We don\'t make mistakes. We just have happy accidents." - Bob Ross'

//     ,   
const double = "\"We don't make mistakes. We just have happy accidents.\" - Bob Ross"

console.log(single);
console.log(double);


Chamar um par de métodos log()resultará no envio de duas linhas idênticas ao console .



"We don't make mistakes. We just have happy accidents." - Bob Ross
"We don't make mistakes. We just have happy accidents." - Bob Ross


Literais de modelo, por outro lado, são declarados usando crases ( ` `):



const template = `Find freedom on this canvas.`


Não há necessidade de escapar aspas simples ou duplas aqui:



const template = `"We don't make mistakes. We just have happy accidents." - Bob Ross


Mas crases em tais strings devem ser escapados:



const template = `Template literals use the \` character.`


Literais de modelo têm todos os recursos de strings regulares. Portanto, você provavelmente pode substituir todas as strings em seu projeto por literais de modelo sem perder nada. Na maioria das vezes, no entanto, as convenções de codificação especificam que os literais de modelo devem ser usados ​​apenas quando seus recursos especiais são necessários. Strings comuns são sempre declaradas usando aspas simples ou duplas para manter a consistência do código. A base de código do projeto, ao escrever que segue este padrão, será mais fácil de ler para desenvolvedores que não estão familiarizados com ela.



Agora que já falamos sobre como declarar strings usando aspas simples, aspas duplas e aspas invertidas, podemos prosseguir para examinar a primeira força dos literais de modelo. A saber - a possibilidade de descrever strings de várias linhas.



Cordas multilinha



Nesta seção, falaremos primeiro sobre como as strings de várias linhas foram declaradas antes do ES6 e, em seguida, veremos como os literais de modelo simplificam essa tarefa.



Inicialmente, se você tivesse que inserir uma variável de string consistindo em várias linhas em um editor de texto, o operador de concatenação de string era usado . O seguinte exemplo de concatenação de string ilustra essa ideia:



const address =
  'Homer J. Simpson' +
  '742 Evergreen Terrace' +
  'Springfield'


Essa abordagem pode permitir que você divida linhas longas em pequenos pedaços e organize-as em um editor de texto em várias linhas. Mas isso não afeta de forma alguma o resultado da linha final. Nesse caso, o valor da constante da string estará localizado em uma linha. As partes das quais o valor da string é montado não serão separadas por avanços de linha ou espaços. Se você imprimir uma constante no console address, o seguinte aparecerá lá:



Homer J. Simpson742 Evergreen TerraceSpringfield


Outra abordagem para escrever tais linhas em editores de código é usar o caractere de barra invertida ( \), que é colocado no final dos fragmentos de linha e, após o qual, em uma nova linha, novos fragmentos são localizados:



const address =
  'Homer J. Simpson\
  742 Evergreen Terrace\
  Springfield'


Esta abordagem preserva, por exemplo, os espaços antes dos fragmentos de linha, mas o valor da variável, se impresso no console, será novamente representado por uma única linha:



Homer J. Simpson  742 Evergreen Terrace  Springfield


Você pode criar uma string real de várias linhas usando o caractere de alimentação de linha ( \n):



const address =
  'Homer J. Simpson\n' +
  '742 Evergreen Terrace\n' +
  'Springfield'


Ao exibir um valor de string armazenado no console address, esse valor se estenderá por várias linhas:



Homer J. Simpson
742 Evergreen Terrace
Springfield


No entanto, usar o caractere de nova linha para criar strings de várias linhas não é particularmente conveniente e fácil. Por outro lado, criar strings de várias linhas usando literais de modelo é muito mais fácil e conveniente. Não há necessidade de concatenar strings, não há necessidade de usar nova linha ou barra invertida. Para criar strings multilinhas usando literais de modelo, é bastante simples, no final do próximo fragmento de uma linha, pressione a tecla Entere continue a inserir a próxima linha do literal de modelo:



const address = `Homer J. Simpson
742 Evergreen Terrace
Springfield`


Se você enviar essa constante para o console, o texto terá a mesma aparência do editor:



Homer J. Simpson
742 Evergreen Terrace
Springfield


Aqui deve-se ter em mente que se houver espaços entre os crases usados ​​para alinhar o código, esses espaços serão incluídos no literal do template resultante. Considere o seguinte exemplo:



const address = `Homer J. Simpson
                 742 Evergreen Terrace
                 Springfield`


Embora esse estilo de codificação facilite a leitura, o que chega ao console após a saída não parecerá muito atraente:



Homer J. Simpson
                 742 Evergreen Terrace
                 Springfield


Agora, tendo lidado com strings de várias linhas, vamos falar sobre como você pode incorporar os resultados da avaliação de várias expressões em strings declaradas de maneiras diferentes, ou seja, vamos falar sobre interpolação de expressão.



Interpolando Expressões



Anteriormente, antes do ES6, a concatenação era usada para criar strings dinâmicas que envolviam valores de variáveis ​​ou expressão:



const method = 'concatenation'
const dynamicString = 'This string is using ' + method + '.'


Se você enviar dynamicStringpara o console, terá o seguinte:



This string is using concatenation.


Ao usar literais de modelo, as expressões podem ser incorporadas na string usando espaços reservados. Um espaço reservado é uma construção de visualização ${}. Nesse caso, tudo o que está entre chaves é considerado código JavaScript e tudo que está fora dessa construção é considerado uma string:



const method = 'interpolation'
const dynamicString = `This string is using ${method}.`


Ao enviar dynamicStringpara o console, você obtém o seguinte resultado:



This string is using interpolation.


Um exemplo comum de incorporação de valores em strings é a criação de URLs dinâmicos. O uso de concatenação para este propósito leva ao aparecimento de construções pesadas e inconvenientes. Por exemplo, aqui está uma função que gera uma string de acesso OAuth :



function createOAuthString(host, clientId, scope) {
  return host + '/login/oauth/authorize?client_id=' + clientId + '&scope=' + scope
}

createOAuthString('https://github.com', 'abc123', 'repo,user')


Se você imprimir o resultado desta função no console, obterá o seguinte:



https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user


Ao usar a interpolação, os programadores não precisam mais ser cuidadosos com as aspas que delimitam partes da string ou onde o operador de concatenação está localizado. Aqui está o mesmo exemplo, reescrito usando literais de modelo:



function createOAuthString(host, clientId, scope) {
  return `${host}/login/oauth/authorize?client_id=${clientId}&scope=${scope}`
}

createOAuthString('https://github.com', 'abc123', 'repo,user')


O resultado da função será o seguinte:



https://github.com/login/oauth/authorize?client_id=abc123&scope=repo,user


Você pode usar o método trim () para remover os espaços em branco à esquerda e à direita de uma string criada com um literal de modelo . Por exemplo, no seguinte snippet de código para criar um elemento HTMLcom uma referência personalizada, uma função de seta é usada :



const menuItem = (url, link) =>
  `
<li>
  <a href="${url}">${link}</a>
</li>
`.trim()

menuItem('https://google.com', 'Google')


Os espaços à esquerda e à direita serão removidos da linha final para garantir que o elemento seja renderizado corretamente:



<li>
  <a href="https://google.com">Google</a>
</li>


Expressões inteiras podem ser interpoladas, não apenas variáveis. Por exemplo - como aqui, onde o resultado da adição de dois números é incorporado em uma string:



const sum = (x, y) => x + y
const x = 5
const y = 100
const string = `The sum of ${x} and ${y} is ${sum(x, y)}.`

console.log(string)


Aqui, a função sum()e as constantes são declaradas xe y. Depois disso, a linha usa a função e essas constantes. Esta é a aparência da constante stringquando impressa no console:



The sum of 5 and 100 is 105.


Esse mecanismo pode ser especialmente útil ao usar o operador ternário , que permite verificar as condições ao formar uma string:



const age = 19
const message = `You can ${age < 21 ? 'not' : ''} view this page`
console.log(message)


A constante messageimpressa no console pode mudar, dependendo se é maior ou menor que 21, o valor armazenado em age. Como esse valor é 19 em nosso exemplo, o seguinte será enviado ao console:



You can not view this page


Agora você sabe como pode se beneficiar da interpolação de expressão ao usar literais de modelo. Na próxima seção, iremos mais longe e exploraremos os padrões de marcação e falaremos sobre como trabalhar com expressões passadas em escopos que correspondem a espaços reservados.



Modelos de tag



Os modelos de tag são uma forma estendida de literais de modelo. Os modelos marcados começam com uma função marcada que analisa o literal do modelo, dando ao desenvolvedor mais controle sobre o processo de geração de string dinâmica.



No exemplo a seguir, criamos uma função tagque planejamos usar no papel de uma função com a qual as operações são realizadas em um modelo de tag. O primeiro parâmetro nomeado desta função stringsé uma matriz de literais de string. Expressões embutidas são colocadas no segundo parâmetro usando a sintaxe dos parâmetros restantes . Para ver o conteúdo desses parâmetros, eles podem ser exibidos no console:



function tag(strings, ...expressions) {
  console.log(strings)
  console.log(expressions)
}


Se você usar uma função ao criar um modelo de tag tag, poderá obter a seguinte construção:



const string = tag`This is a string with ${true} and ${false} and ${100} interpolated inside.`


Como a função tagexecuta a saída para o console stringse expressions, ao executar este código, o seguinte será enviado para o console:



["This is a string with ", " and ", " and ", " interpolated inside."]
[true, false, 100]


Você pode ver que o primeiro parâmetro strings,, é uma matriz contendo todos os literais de string:



"This is a string with "
" and "
" and "
" interpolated inside."


Esse argumento também tem uma propriedade à rawqual você pode se referir strings.raw. Ele contém uma linha na qual nenhuma sequência de escape foi processada. Por exemplo, \nserá apenas um caractere \n, não um comando de alimentação de linha.



O segundo argumento ,, ...expressionsé uma matriz contendo todas as expressões:



true
false
100


O resultado é que as tagexpressões e literais de string são passadas para a função de modelo de tag . Observe que a função não é necessária para retornar uma string. Ele pode trabalhar com os valores passados ​​a ele e retornar qualquer coisa. Por exemplo, podemos ter uma função que não dá atenção a nada e apenas retorna null. É assim que a função é escrita returnsNullno seguinte exemplo:



function returnsNull(strings, ...expressions) {
  return null
}

const string = returnsNull`Does this work?`
console.log(string)


Como resultado da execução deste código, o seguinte aparecerá no console:



null


Como um exemplo do que você pode fazer em um modelo com tags, você pode fazer alterações em cada uma das expressões, como alterações para incluir expressões em tags HTML. Vamos criar uma função boldque adiciona tags para <strong>tanto </strong>o início eo fim de cada expressão:



function bold(strings, ...expressions) {
  let finalString = ''

  //    
  expressions.forEach((value, i) => {
    finalString += `${strings[i]}<strong>${value}</strong>`
  })

  //    
  finalString += strings[strings.length - 1]

  return finalString
}

const string = bold`This is a string with ${true} and ${false} and ${100} interpolated inside.`

console.log(string)


Aqui, expressionsum loop forEach é usado para percorrer o array . Cada elemento é colocado entre tags <strong></strong>.



This is a string with <strong>true</strong> and <strong>false</strong> and <strong>100</strong> interpolated inside.


Em bibliotecas JavaScript populares, você pode encontrar vários exemplos de uso de modelos de tag. Por exemplo, a biblioteca graphql-tag usa um modelo literal gqlpara analisar strings de consulta GraphQL e transformá-las em uma árvore de sintaxe abstrata (AST) que GraphQL entende:



import gql from 'graphql-tag'

//        5
const query = gql`
  {
    user(id: 5) {
      firstName
      lastName
    }
  }
`


A funcionalidade de modelo com tag também é usada na biblioteca de componentes estilizados , que permite criar novos componentes React a partir de elementos DOM regulares e aplicar estilos CSS adicionais a eles :



import styled from 'styled-components'

const Button = styled.button`
  color: magenta;
`

// <Button>     


Como alternativa, você pode usar o método String.raw padrão, aplicando-o a modelos marcados para evitar o processamento de sequências de escape:



const rawString = String.raw`I want to write /n without it being escaped.`
console.log(rawString)


O seguinte aparecerá no console após a execução deste código:



I want to write /n without it being escaped.


Resultado



Neste artigo, lembramos as informações básicas sobre literais de string comuns, formatados com aspas simples ou duplas, e também falamos sobre literais de modelo e modelos de tag. Literais de modelo simplificam muitas tarefas de processamento de strings. Em particular, estamos falando sobre a incorporação de valores diferentes em strings e sobre a criação de strings multilinhas sem usar concatenação ou escape. A marcação é um recurso literal de modelo avançado útil, usado em muitas bibliotecas populares.



Você usa literais de modelo?






All Articles