0

I know there are a ton of questions about eval() alternatives, but I don't think I've come across anything like what I'm trying to do. I apologize if I've come across an answer and just didn't realize it.

Instead of creating a bunch of variables like this

let layerHomes = L.layerGroup().addTo(map);
let layerBusinesses = L.layerGroup().addTo(map);
let layerParks = L.layerGroup().addTo(map);

How would I do it like this, but without eval()?

array = ['Homes', 'Businesses', 'Parks'];

array.forEach((name) => {
    let layer = `$layer{name} = L.layerGroup().addTo(map)`;
    let polylines = `$layer{name}Polylines = L.layerGroup().addTo(map)`;
    eval(layer);
    eval(polylines);
});

I've tried using Function()...

collections.forEach((array) => {
    new Function(array, `let layer${array} = L.layerGroup().addTo(map);`);
    new Function(array, `let layer${array}Polylines = L.layerGroup().addTo(map);`);
});

...but I'm receiving an error: Unhandled Promise Rejection: ReferenceError: Can't find variable: layerHomesPolylines

Which is weird, because layerHomes doesn't throw an error, but layerHomesPolylines does?

How do I accomplish this without eval?

timgavin
  • 4,972
  • 4
  • 36
  • 48
  • 1
    But you have considered `const layer = { homes: L.layerGroup().addTo(map), businesses: L.layerGroup().addTo(map), parks: L.layerGroup().addTo(map) }, layerPolylines = {}; [ "homes", "businesses", "parks" ].forEach((name) => { layer[name] = L.layerGroup().addTo(map); layerPolylines[name] = L.layerGroup().addTo(map); });`, since you _know_ about “a ton of questions about `eval` alternatives”, right? Have you read [“Variable” variables in JavaScript](/q/5187530/4642212)? – Sebastian Simon Jan 08 '23 at 02:24
  • 1
    Consider where your time is going. Is time spent trying to figure out this solution better than manually adding the variables? – Cjmarkham Jan 08 '23 at 02:27
  • 1
    One of the problems with doing this is that even if you find a great way of creating such variables, how are you going to *use* them? Every expression involving the variables will pose exactly the same problem, unless you know the names of the variables that will be created. And if you know the names, then you don't have to do this in the first place. – Pointy Jan 08 '23 at 02:35

1 Answers1

0

You can assign them as properties to this, as it by default refers to the current Window object. This is also what you're seemingly doing with your array variable, it's added as a property to window since you're not using const/let/var.

When nesting into other scopes, however, you have to refer to them through the window object directly; which could defeat the purpose of this altogether... and as such, you should instead create an object that is tasked to hold these properties, see second example.

array = ['Homes', 'Businesses', 'Parks'];

array.forEach((name) => {
    this[`layer${name}`] = L.layerGroup().addTo(map);
    this[`layer${name}Polylines`] = L.layerGroup().addTo(map);
});

E.g. this results in Homes layer Parks poylines

const layers = {};

const array = ['Homes', 'Businesses', 'Parks'];

array.forEach((name) => {
    layers[`${name}`] = `${name} layer`;
    layers[`${name}Polylines`] = `${name} poylines`;
});

console.log(layers["Homes"], layers["ParksPolylines"]);
Nora Söderlund
  • 1,148
  • 2
  • 18
  • 3
    Please prefer `globalThis` over `this`, if anything. Just `this` won’t work in modules. Even then, polluting the global object is not a good idea, so definitely go with the `const layers` approach. – Sebastian Simon Jan 08 '23 at 02:39