Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a JS Object as the scope to a JS Template Literal?

In python, you can do variable string interpolation like this:

song_context = { "adjective": "funny" }
ella_sings = "my {adjective} valentine".format(**song_context)

Here, the song_context object formats variables in the ella_sings string.

In ES6 is there a built-in way to do something like this with template literals? I'm looking for a quick way to explicitly define a substitution space for a given string. Ex:

const song_context = { adjective: "funny" }
const ella_sings = `my ${adjective} valentine`.format(song_context)

Context: I know other ways to do this, e.g. use a template library or do multiple find and replace, but am wondering if any portion of ES6 supports this use case out of the box. I skimmed the template literal part of the ECMAScript 6.0 standard and it pretty clearly states "Let ctx be the running execution context" but it seems kind of hard to believe they wouldn't provide a way to be more explicit about the context when necessary.

like image 387
Myer Avatar asked Sep 26 '17 18:09

Myer


2 Answers

In ES6 is there a built-in way to do something like this with template literals?

Template literals have no special logic. The code between the ${..} brackets is just a normal expression that gets evaluted to a value.

`my ${adjective} valentine`

is always going to look for a variable named adjective in the local scope. You can certainly change it to do

`my ${song_context.adjective} valentine`

If you don't want to change that part of it, then you can always use destructuring, e.g.

const {adjective} = song_context;
const ella_sings = `my ${adjective} valentine`

or use an IIFE:

const ella_sings = ({adjective}) => `my ${adjective} valentine`)(song_context);

You can also build your own templating system around template literals if you want, but it starts getting complicated fast and loses most of the benefits that make you want to use template literals in the first place.

like image 152
loganfsmyth Avatar answered Sep 23 '22 17:09

loganfsmyth


You might want to read up a bit more on them over at the Javascript MDN and pay attention to the section called Tagged template literals as it shows how you can turn a template literal into a full on template.

For archival purposes I'm going to import the relevant section:

Tagged template literals

A more advanced form of template literals are tagged template literals. Tags allow you to parse template literals with a function. The first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions. In the end, your function can return your manipulated string (or it can return something completely different as described in the next example). The name of the function used for the tag can be named whatever you want.

var person = 'Mike';
var age = 28;

function myTag(strings, personExp, ageExp) {

  var str0 = strings[0]; // "that "
  var str1 = strings[1]; // " is a "

  // There is technically a string after
  // the final expression (in our example),
  // but it is empty (""), so disregard.
  // var str2 = strings[2];

  var ageStr;
  if (ageExp > 99){
    ageStr = 'centenarian';
  } else {
    ageStr = 'youngster';
  }

  return str0 + personExp + str1 + ageStr;

}

var output = myTag`that ${ person } is a ${ age }`;

console.log(output);
// that Mike is a youngster

Tag functions don't need to return a string, as shown in the following example.

function template(strings, ...keys) {
  return (function(...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function(key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join('');
  });
}

var t1Closure = template`${0}${1}${0}!`;
t1Closure('Y', 'A');  // "YAY!"
var t2Closure = template`${0} ${'foo'}!`;
t2Closure('Hello', {foo: 'World'});  // "Hello World!"

These tagged template literals seem to be exactly what you want.

like image 26
Robert Mennell Avatar answered Sep 23 '22 17:09

Robert Mennell