I encountered an error today - TypeError: "fa" is not a function
- and after a short investigation, I found the cause. I had forgotten a comma in an object literal, which left me with what amounted to a string followed by a template string, essentially this: "fa"``
. Having seen not a function
I expected to find some offending parentheses and found this curious, so I deepened my investigation in a Node REPL.
''`` // TypeError: '' is not a function
'foo'`` // TypeError: 'foo' is not a function
1`` // TypeError: 1 is not a function
(() => 'foobar')`` //'foobar'
Okay, so I found out that a template string seems to work similarly to putting parentheses after a token. Curiouser and curiouser.
I wondered whether it passes along any arguments, so I wrote this:
function showArgs () {
return arguments
}
showArgs() // {}
showArgs`` // { '0': [ '' ] }
showArgs`foo` // { '0': [ 'foo' ] }
showArgs`foo${'bar'}` // { '0': [ 'foo', '' ], '1': 'bar' }
showArgs`foo${'bar'}${1}` // { '0': [ 'foo', '', '' ], '1': 'bar', '2': 1 }
showArgs(`foo${'bar'}${1}`) // { '0': 'foobar1`' }
What is going on here?
The arguments obviously have something to do with the template string, as they can be used to construct it by concatinating the nth array item with the n + 1th argument and joining them all, but why is the template string executing the preceding token with those arguments?
Look into tagged template literals.
A more advanced form of template literals are tagged template literals. With them you are able to modify the output of template literals using a function. The first argument contains an array of string literals [...]. The second, and each argument after the first one, are the values of the processed (or sometimes called cooked) substitution expressions [...]. In the end, your function returns your manipulated string.
An example from MDN:
var a = 5;
var b = 10;
function tag(strings, ...values) {
console.log(strings[0]); // "Hello "
console.log(strings[1]); // " world "
console.log(strings[2]); // ""
console.log(values[0]); // 15
console.log(values[1]); // 50
return "Bazinga!";
}
tag`Hello ${ a + b } world ${ a * b }`;
// "Bazinga!"