Backticks chamando uma função

96

Não tenho certeza de como explicar isso, mas quando corro

console.log`1`

No google chrome, recebo resultados como

console.log`1`
VM12380:2 ["1", raw: Array[1]]

Por que o crase está chamando a função de log e por que está criando um índice de raw: Array[1]?

Pergunta levantada na sala JS por Catgocat, mas nenhuma resposta fazia sentido além de algo sobre modelagem de strings que realmente não se encaixava no motivo disso estar acontecendo.

Sterling Archer
fonte

Respostas:

70

É chamado Tagged Template no ES-6, mais poderia ser lido sobre eles. Aqui , engraçado, achei o link na seção estrelada do próprio chat.

Mas a parte relevante do código está abaixo (você pode basicamente criar uma classificação filtrada).

function tag(strings, ...values) {
  assert(strings[0] === 'a');
  assert(strings[1] === 'b');
  assert(values[0] === 42);
  return 'whatever';
}
tag `a${ 42 }b`  // "whatever"

Basicamente, é apenas marcar o "1" com a função console.log, como faria com qualquer outra função. As funções de marcação aceitam valores analisados ​​de strings de modelo e os valores separadamente nos quais outras tarefas podem ser executadas.

Babel transpila o código acima para

var _taggedTemplateLiteralLoose = function (strings, raw) { strings.raw = raw; return strings; };

console.log(_taggedTemplateLiteralLoose(["1"], ["1"]));

Como você pode ver no exemplo acima, depois de ser transpilado pelo babel, a função de marcação (console.log) está recebendo o valor de retorno do seguinte es6-> 5 código transpilado.

_taggedTemplateLiteralLoose( ["1"], ["1"] );

O valor de retorno desta função é passado para console.log que irá imprimir o array.

ShrekOverflow
fonte
10
Achei muito mais fácil entender explicantion- wesbos.com/tagged-template-literals
Dave Pile
35

Literal de modelo marcado:

A seguinte sintaxe:

function`your template ${foo}`;

É chamado de literal de modelo com tag.


A função que é chamada como um literal de modelo com tag recebe seus argumentos da seguinte maneira:

function taggedTemplate(strings, arg1, arg2, arg3, arg4) {
  console.log(strings);
  console.log(arg1, arg2, arg3, arg4);
}

taggedTemplate`a${1}b${2}c${3}`;

  1. O primeiro argumento é uma matriz de todos os caracteres de string individuais
  2. O argumento restante corresponde aos valores das variáveis ​​que recebemos via interpolação de string. Observe no exemplo que não há valor para arg4(porque há apenas 3 vezes a interpolação de string) e, portanto, undefinedé registrado quando tentamos registrararg4

Usando a sintaxe do parâmetro rest:

Se não sabemos de antemão quantas vezes a interpolação da string ocorrerá na string do modelo, é frequentemente útil usar a sintaxe do parâmetro rest. Esta sintaxe armazena os argumentos restantes que a função recebe em um array. Por exemplo:

function taggedTemplate(strings, ...rest) {
  console.log(rest);
}

taggedTemplate `a${1}b${2}c${3}`;
taggedTemplate `a${1}b${2}c${3}d${4}`;

Willem van der Veen
fonte
3

Atrasado para a festa mas, TBH, nenhuma das respostas explica 50% da pergunta original ("por que raw: Array[1]")

1. Por que é possível chamar a função sem parênteses, usando crases?

console.log`1`

Como outros apontaram, isso é chamado Tagged Template (mais detalhes também aqui ).

Usando essa sintaxe, a função receberá os seguintes argumentos:

  • Primeiro argumento: um array contendo as diferentes partes da string que não são expressões.
  • Resto de argumentos: cada um dos valores que estão sendo interpolados (ou seja, aqueles que são expressões).

Basicamente, os seguintes são 'quase' equivalentes :

// Tagged Template
fn`My uncle ${uncleName} is ${uncleAge} years old!`
// function call
fn(["My uncle ", " is ", " years old!"], uncleName, uncleAge);

(veja o ponto 2. para entender por que eles não são exatamente iguais)

2. Por que o ["1", raw: Array[1]] ???

O array passado como primeiro argumento contém uma propriedade raw, que permite acessar as strings brutas medida que são inseridas (sem processar sequências de escape).

Exemplo de caso de uso:

let fileName = "asdf";

fn`In the folder C:\Documents\Foo, create a new file ${fileName}`

function fn(a, ...rest) {
  console.log(a); //In the folder C:DocumentsFoo, create a new file
  console.log(a.raw); //In the folder C:\Documents\Foo, create a new file 
}

O quê, um array com uma propriedade ??? ???

Sim, uma vez que os arrays JavaScript são na verdade objetos, eles podem armazenar propriedades .

Exemplo:

const arr = [1, 2, 3];
arr.property = "value";
console.log(arr); //[1, 2, 3, property: "value"]

Ludovico
fonte