Template Strings
JavaScript is one of the most popular programming languages: in the TIOBE Index for December 2014 it occupies the seventh position - right after C, Java, Objective-C, C++, C# and PHP. JS was established as a universal client-side dialect of Web applications since its very inception. Nowadays JavaScript is also a "patois" of the server: Node.js and Node-comparable frameworks have enabled Web authors to define server-based application logic in pure JS. Evolving technologies pose new challenges: JavaScript engines have to borrow more advanced features from other languages, so PHP, Python or Ruby developers using JS can take up recognizable techniques.
One of experimental technologies proposed in the ECMAScript 6 draft. is template strings. The concept of template strings is well known to developers working with C# or dynamic languages employed in server-side scripting. C# strings can assume the form of regular string literals or verbatim string literals. A verbatim literal consists of an @ character followed by a double-quote character, zero or more characters, and a closing double quote. The characters representing the string contents are interpreted verbatim, i.e. simple escape sequences are not processed:
using System;
class Demo {
static void Main()
{
string regularLiteral="This \tis \ta \tregular \tstring \tliteral.";
Console.WriteLine(regularLiteral);
string verbatimLiteral=@"This \tis \ta \tverbatim \tstring \tliteral.";
Console.WriteLine(verbatimLiteral);
}
}
In regular strings the backlash (\) informs the compiler that the next character is special. The \t is an escape sequence designating the horizontal tab, so the regularLiteral will contain five tabs. In verbatim literals the backlash is not regarded as an escape, so is is included in the output as an ordinary character. After the code above is compiled, the running executable will produce the following result:
This is a regular string literal.
This \tis \ta \tverbatim \tstring \tliteral.
One of useful features of verbatim literals is their support for multiline strings. Let's display an extract from The Cask of Amontillado by Edgar Allan Poe as a regular literal. The extract must retain a single quote and double quotes as well as provide spaces between lines of text. We presume that the underlying OS is Windows, so line endings will be represented as \r\n pairs.
string extract="\r\n\r\n\"I forget your arms.\"\r\n\r\n\"A huge human foot d\'or, in a field azure; the foot crushes a serpent rampant whose fangs are imbedded in the heel.\"\r\n\r\n\"And the motto?\"\r\n\r\n\"Nemo me impune lacessit.\"";
The string is too long and has too many escapes for quotes, carriage returns and new lines. The use of a verbatim literal with the same contents makes the code more readable:
string multiline=@"
""I forget your arms.""
""A huge human foot d'or, in a field azure; the foot crushes a serpent rampant whose fangs are imbedded in the heel.""
""And the motto?""
""Nemo me impune lacessit.""
";
Both regular and verbatim literals produce the identical output:
"I forget your arms."
"A huge human foot d'or, in a field azure; the foot crushes a serpent rampant whose fangs are imbedded in the heel."
"And the motto?"
"Nemo me impune lacessit."
JavaScript template strings work in the same fashion:
var textArea=document.querySelector("textarea");
textArea.value=`"Amontillado!"
"I have my doubts."
"Amontillado!"
"And I must satisfy them."
"Amontillado!"`;
A template string starts with the special grave (`) character (the ASCII code is 96). The auxiliary String.raw() function can be employed to create verbatim literals in JavaScript:
// an extract from Alice's Adventures in Wonderland
var extract=String.raw`'Would you tell me, please, which way I ought to go from here?'
'That depends a good deal on where you want to get to,' said the Cat.
'I don't much care where - ' said Alice.
'Then it doesn't matter which way you go,' said the Cat.
`;
Preserving characters in long lines of text is not the only trait of JS template strings. Another useful technique is interpolation of variables: when a variable is embedded in a template, it is parsed, and its value is included in the resultant string. Besides, inline expressions are evaluated. Analogous functionality can be found in server-side scripting languages such as PHP, Perl or Ruby. The example below launches one of PHP functions to represent the "PHP" string as a Base64 sequence:
<?php
$encoded=base64_encode("PHP");
echo "The \"PHP\" string is encoded as $encoded.";
?>
The output is
The "PHP" string is encoded as UEhQ.
PHP also supports the syntax based on the use of the curly braces:
echo "The \"PHP\" string is encoded as {$encoded}.";
echo "The \"PHP\" string is encoded as ${encoded}."; // the same output
Ruby applies the sharp character (#) to evaluate an embedded expression:
require "base64"
puts "'Ruby' is encoded as #{Base64.encode64('Ruby')}"
The resulting string is
'Ruby' is encoded as UnVieQ==
Evaluating expressions in JS template strings resembles similar operations in other languages:
console.log(`'JavaScript' is encoded as ${btoa('JavaScript')}`);
An expression to evaluate must begin with the dollar sign. Embedded expressions can contain one of JavaScript standard functions: in the example above, this is btoa() - a Base64 utility method converting a Unicode string to its Base64 representation. The output is logged out as
'JavaScript' is encoded as SmF2YVNjcmlwdA==
Here's a more complicated example: the code below computes the square root of positive numbers inserted by the user.
input element
<input type="number" oninput="computeSquareRoot(this.valueAsNumber)">
computing square roots of inserted numbers
var log=document.querySelector("#log"); // a UI element for displaying result
function computeSquareRoot(number) {
if(isNaN(number)==false&&number>0) {
log.textContent=`The square root of ${number} is ${Math.sqrt(number)}.`;
}
else {
log.textContent="";
}
}
The same example could be drawn up by using a tagged template string: strings are passed to a special function parsing and modifying them.
input element
<input
type="number"
oninput="computeSquareRoot`The square root of ${this.valueAsNumber} is ${Math.sqrt(this.valueAsNumber)}.`">
computing square roots of numbers
function computeSquareRoot(strings, ...values) {
if(isNaN(values[0])==false&&values[0]>0) {
log.textContent=strings[0]+values[0]+strings[1]+values[1]+strings[2];
}
else {
log.textContent="";
}
}
The function computeSquareRoot() accepts two arguments. The first argument is an array of string literals:
console.log(strings); // Array [ "The square root of ", " is ", "." ]
The second argument is an array holding resulting values of interpolation. Note the use of the spread operator (...values
). The operator is one of new features proposed in EcmaScript 6: it allows expressions to be expanded where multiple arguments for function calls are due. If the <input> element has the value of 9, then the following array is passed to the input handler:
console.log(values); // Array [ 9, 3 ]
ECMAScript 6 compatibility table reflects the current status of template strings implementation: for example, the latest stable release of Firefox supports template strings natively. As the technology is still considered experimental, its syntax and behavior may change in future versions of major browsers. However, the essentials of template strings will remain the same: verbatim string literals can significantly enhance manipulation and formatting of textual content on the Web.