1

I bumped into this question (how to init an array like [{id: 1},{id: 2},...]).

Accepted answer is:

let sampleData = Array.from({length: 10}, (_, i) => ({id:i}))

console.log(sampleData)

And there are plenty others.
However, I thought of template literals as a solution, but I can't figure out how to make it work.

What I have so far is:

var i = 0;
var arr = `[${"{id:++i},".repeat(10)}]`
console.log("As a string",arr);
console.log("Evaluated",eval(arr));

However, it uses eval which I know it's wrong.

I also tried

var i = 0;
var arr = `[${"{id:${++i}},".repeat(10)}]`
console.log(arr);

But I have yet to somehow call the back ticks on this string (something like TemplateLiteralFunction.call on arr), to parse those expressions.
And instead of writting a tag function I'd just write a function called initArray(ofLength).

So, is there anyway you can use template literals without eval or tag functions and achieve an array of a given length filled with values? Perhaps somehow nesting template literals?

Adelin
  • 7,809
  • 5
  • 37
  • 65
  • Using a template litteral means you are working with a string in the end, and it won't be very good in a performance point of view. You can try to use `JSON.parse`, which is better than `eval` but no more `++i`... :/ – sjahan Jul 26 '18 at 08:09
  • well yes in the end `JSON.parse` will be needed, but I've yet to create the JSON compliant string with the `++i` already evaluated. Performance is not a problem here. It can be slow, what I'm wondering is if it is possible without `eval` or tag functions – Adelin Jul 26 '18 at 08:14

1 Answers1

3

You can use Function constructor

The Function constructor creates a new Function object. Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues similar to eval. However, unlike eval, the Function constructor allows executing code in the global scope, prompting better programming habits and allowing for more efficient code minification.

var template = `[${"{\"id\":${++i}},".repeat(10)}]`
template = template.replace(/,]$/,']'); //replace last comma

var parser = new Function("{i}", "return `" + template + "`;");
var arr = parser({i:0});
console.log(JSON.parse(arr)); 
Vladu Ionut
  • 8,075
  • 1
  • 19
  • 30
  • Yup. +1 although it's very close to `eval` but I failed to specify Function constructor so that's my bad. I will wait some time to see if there's a cleaner solution otherwise I'll accept yours. Thanks! Hai Romania! – Adelin Jul 26 '18 at 08:56