javascriptecmascript-6template-literalstagged-templates

In ES2015, how do you reconstruct a tagged template literal in the correct order?


Using the example from the MDN docs on template literals, we can create custom "tag" functions.

var a = 5;
var b = 10;

function tag(strings, ...values) {
    console.log(strings[0]);
    console.log(strings[1]);
    console.log(values[0]);
    console.log(values[1]);

    return strings[0] + ' ' + values[0] + ' ' + strings[1] + ' ' + values[1];
}

tag`Hello ${ a + b } world ${ a * b }`;

From here, how do we construct the message in the same order it was fed in when mixing strings with values?

The above tag function would fail to maintain order when swap the value/string order, such as:

tag`Hello ${ a + b } world ${ a * b }`;
// swapped to
tag`${ a + b } hello ${ a * b } world`;

Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals


Solution

  • strings.length will always be greater than ...values.length by one. The first value of strings will always be the content of the template string up to the first substitution. When a substitution is the first value of the template string, strings[0] is an empty string. The same goes for when the last value of the template string is a substitution, strings[strings.length-1] is an empty string.

    So in your example, you output the empty string as strings[0] and strings[1] becomes hello, but you never output strings[2] for world. The correct way to rejoin the strings is to assign the first index of strings to a string, then loop over all the values and add them together in order.

    function tag(strings, ...values) {
      var str = strings[0];
      for (i = 0; i < values.length; i++) {
        str += values[i] + strings[i+1];
      }
    
      return str;
    }