Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template literals and parentheses-less function calls

I recently learned that ES6 allows to make function calls without parentheses when using a template literal as a parameter. E.g.

showstring`Hello World`;

After reading a few articles on this functionality, however, I have come away with scant information as to the logic behind how JS handles these calls.

After playing around with some permutations of my code, I am still struggling to piece together the pattern of how a template literal is broken down inside the function when one calls it that way.

const showstring = (str) => {
  console.log(str);
}
showstring`Hello World`;

What happens in the above code is straightforward, the string literal is received as an array where the first and only element is the string.

Where it gets a bit confusing is once I start using expressions inside the template. E.g.

const showstring = (str, ...values) => {
  console.log(str);
  console.log(values)
}
const name = 'John'
showstring`Hello World ${name} ${name} ${1 + 2} and more`;

So it looks like the ...values part destructures all the expressions. But why, then, does the str array have empty strings in those spots?

I just don't fully grasp the pattern it follows here. Can someone explain this feature? Or perhaps point me to a good article?

like image 279
codemonkey Avatar asked Jan 16 '21 07:01

codemonkey


People also ask

What are the advantages of using template literals?

In addition to its syntactical differences there are two very specific advantages to using template literals: Multi-line strings: A single string can span two or more lines. Expression Interpolation: Javascript variables and expressions can be inserted directly in the string.

Are template literals faster?

popular templaters like mustache/underscore/handlebars are dozens to hundreds of times slower than concatenation is or template literals will be. Theoretical speaking (unless the JS is compiled), template literals would be slower since the 'string' needs to be parsed regardless of placeholder existence.

What are template literals for?

Template literals are literals delimited with backtick (`) characters, allowing for multi-line strings, for string interpolation with embedded expressions, and for special constructs called tagged templates.

Are Backticks slower than other strings in JavaScript?

The speed of string literals in JavaScript He said backtick literals are less performant (in other words, slower) because they need to processed. In other words, the variable interpolation that we want from backtick literals are an Achilles' heel — processing the template literals slows performance.


Video Answer


1 Answers

In the second code snippet, these are logged:

// str
[
  "Hello World ",
  " ",
  " ",
  " and more"
]

// values
[
  "John",
  "John",
  3
]

If by those "empty strings" you mean the 2nd and 3rd item of the str array, they are not empty strings; they are strings with a single space. They come from the spaces between the expressions in the template literal:

showstring`Hello World ${name} ${name} ${1 + 2} and more`;
//                            ^       ^

When a template literal is preceded by an expression – in this case showstring – it's called a tagged template.

In your showstring function, str contains always one more item than the values array. E.g. take a look at what these log:

const showstring = (str, ...values) => {
  console.log(str);
  console.log(values)
}
const name = 'John'
showstring``;
showstring`${name}`;
showstring`Hello ${name}!`;

This isn't specific to your function; this is how tagged templates work. From the Tagged templates section in the book JavaScript for impatient programmers (ES2020 edition):

The function before the first backtick is called a tag function. Its arguments are:

  • Template strings (first argument): an Array with the text fragments surrounding the interpolations ${}.
  • Substitutions (remaining arguments): the interpolated values.

About your comment:

Interestingly though, that single space will always remain a single space no matter how many spaces you put between the expressions when calling the function. Any idea why it trims to just one space?

This doesn't seem to be the case. This logs a string with three spaces:

const showstring = (str, ...values) => {
  console.log(str);
  console.log(values)
}
const name = 'John'
showstring`Hello ${name}   ${name}!`;

Were you maybe printing the results to the DOM? Multiple spaces are shown as only one unless you are using <pre> or white-space: pre; or something similar, so it might seem that the results are trimmed to just one space.

like image 141
Matias Kinnunen Avatar answered Oct 18 '22 18:10

Matias Kinnunen