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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With