Convert a string to a template string
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);
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+'`');
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.
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. :(