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.


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.


10

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}`;


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"]

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.