javascriptecmascript-6template-literalstagged-templates

Are sibling substitutions combined in tagged templates?


Take into consideration the following:

String.raw`Test ${123}${'abc'}`;
String.raw`Test ${123 + 'abc'}`;

Is ${123}${'abc'} equivalent to ${123 + 'abc'}? In other words, are ciblings converted to the ${123 + 'abc'} format behind the scenes?

Also, how would someone handle this specific case in their own tagged template function?


Solution

  • With String.raw, the behavior is essentially the same. Both it and + (with a string value) perform concatenation, achieving the same result.


    The difference between them is that the 1st line is deferring the concatenation for String.raw to perform, with ${123} and ${'abc'} provided to it as separate arguments.

    In using +, the concatenation is always performed upfront, passing only a single value to String.raw for ${123 + 'abc'}.

    function foo(template, ...values) {
      console.log(template, values);
    }
    
    foo`Test ${123}${'abc'}`; // [ 'Test ', '', '' ] [ 123, 'abc' ]
    foo`Test ${123 + 'abc'}`; // [ 'Test ', '' ]     [ '123abc' ]
    

    With other tagged functions, the difference may be more apparent, as the function may perform other operations before (or besides) concatenation.

    A contrived example:

    // adds 99999 to each value
    function bar(template, ...values) {
      var raw = template.raw;
      var result = raw[0];
    
      values.forEach((value, i) => {
         result += value + 99999;
         result += raw[i + 1];
      });
    
      return result;
    }
    
    console.log(bar`Test ${123}${'abc'}`); // 100122abc9999
    console.log(bar`Test ${123 + 'abc'}`); // 123abc99999