1

My app fetch a list of resources strings + placeholders tokens and it should change the token with a given value.

An example of such resource is : "http://example.com/?name=${name}&age=${age}";

(I get many like these in an array but that's not relevant).

So now I have this^ string and I have the values. So I need to generate the digested string.

Sure I can use eval :

var template = "http://example.com/?name=${name}&age=${age}";
var name = "John";
var age = "30";
var url = eval(`\`${template}\``);
console.log(url); //http://example.com/?name=John&age=30

This works.But I don't want to use eval.

So I've switched to other approach of new Function()() :

var url = new Function ('tmpl','obj','return `${tmpl}`')

This yields the function:

ƒ anonymous(tmpl,obj ) {
return `${tmpl}`
}

So now I can do :

new Function ('tmpl','obj','return `${tmpl}`')(template ,{name, age})

But now I need to break apart obj within the inner function so that the template literal will know the values

BTW - I've tried this - with no success:

(new Function ('tmpl','obj','return `${tmpl}`').bind({name,age})) (template)

Question

How can I flatten obj in the inner function so that ${} will have known local values?

Nb I prefer not to go to regex solutions becuase of line breaks pros in template literals. and besides , those resources are intentionally in a format of es6 template strings

Online-demo

5
  • 2
    You still have to eval to convert the string to a template. Using a function doesn't change that. Commented Feb 28, 2018 at 16:32
  • @KevinB the function returns a template "return ${tmpl}" Commented Feb 28, 2018 at 16:34
  • Yes, but that's not going to do what you are asking for. Commented Feb 28, 2018 at 16:34
  • Your function doesn't even work. It just returns the tmpl as a string. Commented Feb 28, 2018 at 16:34
  • 2
    You're using template literal for something it wasn't intended for. This is why we still have template engines in ES6. Commented Feb 28, 2018 at 16:34

2 Answers 2

2

I've managed to solve this with template strings as I wanted .

setString(resource: string, obj: {}) {
    const names = Object.keys(obj);
    const vals = Object.keys(obj).map(key => obj[key]);
    return new Function(...names, `return \`${resource}\`;`)(...vals);
  }

var str = "We've sent your code to ${phone}.";
console.log(this.setString(str, { phone: 123 }))

Output:

"We've sent your code to 123."

Demo

Sign up to request clarification or add additional context in comments.

3 Comments

So you don't want to use eval, but are OK with new Function? I hope you realise they essentially do the same thing...: parse a dynamic string as code at run time.
New function is not like eval. Eval has access to the local variable of my local method . Sure i could move eval to a seperate method but besides that eval creates a new execution context whereas function not
Both parse a string as code at run-time, which is the major concern with eval: the same concern is applicable to new Function. That is my point.
1

The proper new Function replacement for your eval solution is

var template = "http://example.com/?name=${name}&age=${age}";
var makeUrl = new Function("{name, age}", "return `" + template + "`;");
var url = makeUrl({name: "John", age: 30});
console.log(url); //http://example.com/?name=John&age=30

Your function had just been returning the tmpl string that was passed into it.

2 Comments

Bergi - this means that I have to write each time the params part in : new Function("{name, age}". ( different resources might have different tokens) ...Anyway to make it dynamic ?
Yes, you need to decide at some point which variables to make available. You could do new Function("obj", "with (obj) { return "+template+"; }"), but it's obviously not recommended. You can build the destructuring expression from whatever source you have available.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.