Function call <Function>`<Parameter>`

Asked

Viewed 81 times

3

I am currently studying Webcomponents, Polymer, Litelement and so I came across this feature of creating the template using Litelement that I had never seen before:

html`<div>Teste</div>`

Same goes for CSS:

css`div {color: blue}`

The code can be checked here and the result here

Trying to better understand how this statement js went into the source code and found that it is just a function difference:

/**
 * Interprets a template literal as an HTML template that can efficiently
 * render to and update a container.
 */
export const html = (strings: TemplateStringsArray, ...values: unknown[]) =>
  new TemplateResult(strings, values, 'html', defaultTemplateProcessor);

So I tried to implement something like this to understand how it works:

html = (t, i) => {
  console.log(t, i);
  console.log(typeof t, typeof i);
}

html('teste');

html`teste`;

On the console appears:

inserir a descrição da imagem aqui

What made me understand this statement even less:

<function>`<parameter>`

Where I pass a string and actually I get an object that looks like an array.... after all, what is this statement about? And how do I reach the second variable of the function? What are the real benefits and when should I use this type of statement? Does it have anything to do with String.raw()?

1 answer

6


This notation is called tagged template. When the function is invoked with this notation, the received string is transformed into an array using placeholders ${} as delimiters, and the values within the delimiters are passed as the other parameters.

That is to say:

function log(strings, ...values) {
  console.log(strings, values)
}

log `<ul> <li>${123}</li> <li>${456}</li> </ul>`

Will generate a list containing <ul> <li>, </li> <li> and </li> </ul> in strings, and all other values will be collected in values because of the operator ..., generating a list containing 123 and 456.


What is the advantage of that?

You can create a "middleware" function to run before Javascript assigns placeholders values in its literal string.

function toUpper(strings, ...values) {
  var upperValues = values.map(v => v.toUpperCase())
  return String.raw(strings, ...upperValues)
}

var company = "Alfreds Futterkiste"
var contact = "Maria Anders"
var country = "Germany"

var template = toUpper `
  <tr>
    <td>${company}</td>
    <td>${contact}</td>
    <td>${country}</td>
  </tr>`

console.log(template)

Not a terribly useful example, you could also call the method toUpperCase manually on each variable, but that’s the idea.


Another classic use case is to escape HTML tags by preventing XSS attacks, example taken from here:

function sanitize(strings, ...values) {
  const dirty = strings.reduce((prev, next, i) => `${prev}${next}${values[i] || ''}`, '');
  console.log(dirty);
  console.log(aboutMe);
  return DOMPurify.sanitize(aboutMe);
}
const name = 'petyr baelish';
const aboutMe = `I love to do evil <img src="http://unsplash.it/100/100?random" onload="alert('I hacked you. Haha');" />`;
const html = sanitize `
    <h3>${name}</h3>
    <p>${aboutMe}</p>
  `;


console.log(html);
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/0.8.2/purify.min.js"></script>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.