Faiz Mohamed Haneef
Faiz Mohamed Haneef

Reputation: 3596

String interpolation on variable

Say I have a variable str

var str = "123"

Now I could do console.log(`Hello ${str}`) and it will print Hello 123

Now I have another variable strnew

var strnew = 'Hello ${str}'

Note (based on answers/comments) - strnew is read from a file, so its always a string and cant be replaced with `

How do I console.log(...) to print Hello 123

Is it possible wihtout any kind of eval()

Upvotes: 32

Views: 24149

Answers (4)

Kurtis Jungersen
Kurtis Jungersen

Reputation: 2554

I built off of @georg's answer above for a typescript solution:

public renderTemplate(templateStr: string, args: any): string {
  templateStr = templateStr.replace(/`/g, '\\`');
  
  const keys = Object.keys(args);

  const fn = new Function(...keys, 'return `' + templateStr + '`');

  return fn(...keys.map(key => args[key]));
}

The usage is virtually the same as well.

Upvotes: 0

georg
georg

Reputation: 214959

With something as simple as ${str} you can use a simple string replacement:

var template = (tpl, args) => tpl.replace(/\${(\w+)}/g, (_, v) => args[v]);

var tpl = 'Hello ${str} and ${other}';

console.log(template(tpl, {str: 'foo', other: 'bar'}));

In a general case, no, not possible without eval (short of writing your own js interpreter), because ${...} can contain arbitrary expressions.

For completeness' sake, here's the eval solution:

var template = function(tpl, args) {
    var keys = Object.keys(args),
        fn = new Function(...keys, 
          'return `' + tpl.replace(/`/g, '\\`') + '`');
    return fn(...keys.map(x => args[x]));
};


function test() {
    var myTpl = 'Hello ${str + "!"} and ${other.toUpperCase()}';
    console.log(template(myTpl, {str: 'foo', other: 'bar'}));
}

test();

Upvotes: 36

Ivan Koshelev
Ivan Koshelev

Reputation: 4260

Thanks to this answer, here is a bit of black magic code that achieves what you want. Disclaimer - this is for fun / very limited and exotic application. It is likely to be very slow and break down on lots of edge cases, but with a limited scope of your question it works.

function getString(){
	return "calculating ${foo} + ${bar} = ${foo + bar}";
}

var localEnvironmentProxy = new Proxy({}, {
    has(target, prop) { return true; },
    get(target, prop) { return (prop in target ? target : window)[prop]; }
  });
  
  with(localEnvironmentProxy){
  
	var foo = 1;
	var bar = 2;
  
	var templString = getString();
	
	var fnFullText = 'with(arguments[0]){ return `' + templString + '`;}';
	
	var tempalteFn = new Function(fnFullText);
				
	console.log(tempalteFn(localEnvironmentProxy));
    //calculating 1 + 2 = 3
  
  }

Upvotes: 0

Dmitry Masley
Dmitry Masley

Reputation: 525

You can use function instead of just string.

var strnew = function(str){
  return `Hello ${str}`;
}
var str = "123";
console.log(strnew(str))

Upvotes: 1

Related Questions