javascript - Convert a string to a template string

ID : 20429

viewed : 15

Tags : javascriptecmascript-6evaltemplate-stringsjavascript

Top 5 Answer for javascript - Convert a string to a template string

vote vote

100

In my project I've created something like this with ES6:

String.prototype.interpolate = function(params) {   const names = Object.keys(params);   const vals = Object.values(params);   return new Function(...names, `return \`${this}\`;`)(...vals); }  const template = 'Example text: ${text}'; const result = template.interpolate({   text: 'Foo Boo' }); console.log(result);

vote vote

86

As your template string must get reference to the b variable dynamically (in runtime), so the answer is: NO, it's impossible to do it without dynamic code generation.

But, with eval it's pretty simple:

let tpl = eval('`'+a+'`'); 
vote vote

78

No, there is not a way to do this without dynamic code generation.

However, I have created a function which will turn a regular string into a function which can be provided with a map of values, using template strings internally.

Generate Template String Gist

/**  * Produces a function which uses template strings to do simple interpolation from objects.  *   * Usage:  *    var makeMeKing = generateTemplateString('${name} is now the king of ${country}!');  *   *    console.log(makeMeKing({ name: 'Bryan', country: 'Scotland'}));  *    // Logs 'Bryan is now the king of Scotland!'  */ var generateTemplateString = (function(){     var cache = {};      function generateTemplate(template){         var fn = cache[template];          if (!fn){             // Replace ${expressions} (etc) with ${map.expressions}.              var sanitized = template                 .replace(/\$\{([\s]*[^;\s\{]+[\s]*)\}/g, function(_, match){                     return `\$\{map.${match.trim()}\}`;                     })                 // Afterwards, replace anything that's not ${map.expressions}' (etc) with a blank string.                 .replace(/(\$\{(?!map\.)[^}]+\})/g, '');              fn = Function('map', `return \`${sanitized}\``);         }          return fn;     }      return generateTemplate; })(); 

Usage:

var kingMaker = generateTemplateString('${name} is king!');  console.log(kingMaker({name: 'Bryan'})); // Logs 'Bryan is king!' to the console. 

Hope this helps somebody. If you find a problem with the code, please be so kind as to update the Gist.

vote vote

70

What you're asking for here:

//non working code quoted from the question let b=10; console.log(a.template());//b:10 

is exactly equivalent (in terms of power and, er, safety) to eval: the ability to take a string containing code and execute that code; and also the ability for the executed code to see local variables in the caller's environment.

There is no way in JS for a function to see local variables in its caller, unless that function is eval(). Even Function() can't do it.


When you hear there's something called "template strings" coming to JavaScript, it's natural to assume it's a built-in template library, like Mustache. It isn't. It's mainly just string interpolation and multiline strings for JS. I think this is going to be a common misconception for a while, though. :(

vote vote

53

There are many good solutions posted here, but none yet which utilizes the ES6 String.raw method. Here is my contriubution. It has an important limitation in that it will only accept properties from a passed in object, meaning no code execution in the template will work.

function parseStringTemplate(str, obj) {     let parts = str.split(/\$\{(?!\d)[\wæøåÆØÅ]*\}/);     let args = str.match(/[^{\}]+(?=})/g) || [];     let parameters = args.map(argument => obj[argument] || (obj[argument] === undefined ? "" : obj[argument]));     return String.raw({ raw: parts }, ...parameters); } 
let template = "Hello, ${name}! Are you ${age} years old?"; let values = { name: "John Doe", age: 18 };  parseStringTemplate(template, values); // output: Hello, John Doe! Are you 18 years old? 
  1. Split string into non-argument textual parts. See regex.
    parts: ["Hello, ", "! Are you ", " years old?"]
  2. Split string into property names. Empty array if match fails.
    args: ["name", "age"]
  3. Map parameters from obj by property name. Solution is limited by shallow one level mapping. Undefined values are substituted with an empty string, but other falsy values are accepted.
    parameters: ["John Doe", 18]
  4. Utilize String.raw(...) and return result.

Top 3 video Explaining javascript - Convert a string to a template string

Related QUESTION?