Is there an easy way to create dynamic variables with Javascript?
Asked Answered
S

5

17

I've built a data-driven google map with different icons that get assigned to the map depending on the type of item located. So if I have 5 types of landmark, and each gets a different icon (store, library, hospital, etc.)-- what I'd like to do is generate the google icon objects dynamically. I was thinking something like this:

types = array('hospital','church','library','store',etc);
var i=0;
while (i<=types.length) {

    var landmark + i = new google.maps.Icon();
    landmark.image = "icon" + i + ".png";
    i++;
    } 

however, as you've probably guessed, this doesn't work. I also tried using eval, like this:

while (i<=types.length) {
        doIcon(i);
        i++;
    }   

    function doIcon(i){ 
        eval("var landmark" + i + " = new.google.maps.Icon();");
        return eval("landmark" + i);
    }

but it didn't work either-- I'd appreciate any pointers on generating javascript variables dynamically. It's got to be pure js, I could do it in PHP but that's not an option here.

Thanks!

Statvolt answered 9/3, 2010 at 23:28 Comment(1)
JavaScript really is a dynamic language. You seldom need to use the eval-statement for things like this, because you can mostly write whatever you want as long as the syntax is correct, and if what you've written isn't existing you'll get an runtime-error. A nice thing about javascript is the ability that window.close is the same as writing window["close"]. So you can even write window["close"](); or var c = "close"; window[c]();Lioness
H
33

It's really easy to do: object["variablename"] = whatever;

So for example you could have an object: var Landmarks = {} and you could add to it like so: Landmarks["landmark" + i] = new google.maps.Icon(); and pass it that way.

If you need these variables to be global (why would you?) you can access the global object directly using window.

Hitherto answered 9/3, 2010 at 23:35 Comment(2)
Thanks Plynx! This ended up working fine for me. I appreciate the help.Statvolt
@julio, Plynx: Not sure how to say this without sounding bitter, but this would be terrible javascript. Like I said in my answer, this very thing is what javascript arrays are for. If you're happy to write your javascript like this then fair enough but I think it would make you a better coder if you learned to do it the correct way :-)Portsalut
P
5

If you're going to do it using a declared object such as Landmark["landmark" + i], you really may as well use an index array rather than an associative, it's much easier for iteration. Objects aren't really used with indexed properties because Arrays do a much better job of it:

var myObj =           // object version
{
   "item0": "blah",
   "item1": "blah"
   // etc
}
var myArr =           // array version
[
   "blah",
   "blah"
   // etc
]

Much more sensible to use the array:

landmarks = []; // new array
types = array('hospital','church','library','store',etc);  
var i=0;  
while (i<=types.length) {  
    landmarks.push(new google.maps.Icon());
    landmarks[i].image = "icon" + i + ".png";
    i++;  
}

It makes more sense to do it that way and for...in loops on objects can get a bit messy with prototyped properties being enumerable, etc.

If you're trying to make a variable global, add it to the window object:

var myCustomVar = "landmark" + i;
window[myCustomVar] = new google.maps.Icon();

alert(landmark0);

But this would be polluting the global namespace with many unnecessary variables. So you'd still be better with an array:

window.landmarks = [];
landmarks.push(new google.maps.Icon());
// etc...
Portsalut answered 9/3, 2010 at 23:44 Comment(4)
thanks Andy-- I tried your solution, and it appears that you can't push this object onto an array. I got a syntax error every time I tried. However, when I did it like this: var icon = new google.maps.Icon(); landmarks.push(icon); it worked fine. the problem then became that I'd get a "landmark[i] undefined" if I tried to set the other attributes using landmarks[i].image = etc. Any thoughts?Statvolt
@julio: take a look at the push method docs on MSDN - msdn.microsoft.com/en-us/library/6d0cbb1w(VS.85).aspx. Make sure your landmarks = [] is outside of the loop, too, otherwise you're constantly overwriting it. Trust me, what you're trying to achieve is the reason arrays exist.Portsalut
ps - the push method very usefully returns the new length of the array, so you could check the returned value to see if what you're pushing is making it into the array.Portsalut
Very late to the party I know but presuming no typo in your comment : "landmark[i] undefined" if I tried to set the other attributes using landmarks[i].image = etc. Any thoughts? would be because your array is landmarks not landmark...Ozalid
C
4

Just to answer your question directly (although please note that this is not the solution you want. Check out the other answers. This is just for documentation!), here's a copy-paste from a JavaScript console:

> window["myNamedVar"] = "Hello, World!";
> console.log(myNamedVar);
  "Hello, World!"
Controversy answered 9/3, 2010 at 23:55 Comment(0)
C
3

You'd be better off creating a javascript object which you can use somewhat like an associative array is used in PHP:

var types = ['hospital','church','library','store'];
var landmarks= {};
for (var i in types) {
    landmarks[types[i]]= new google.maps.Icon();
    landmarks[types[i]].image = "icon" + i + ".png";
} 
alert(landmarks['hospital'].image);  // displays "icon0.png"
Charades answered 9/3, 2010 at 23:36 Comment(0)
H
1

Do you really need those variables? Can't you do with this:

var types = ['hospital','church','library','store'];    
for(var i =0; i < types.length; i += 1) (new google.maps.Icon()).image = "icon" + i + ".png";

Modifications done based on comment:

icon name pattern changed from icon + index + .png to icon + type + .png and saving the results of the loop.

types = ['hospital','church','library','store'];
var landmarks = {};


// images names are of the form icon + type + .png
function createIcon(type) 
{ 
    var icon = new google.maps.Icon();
    icon.image = "icon" + type + ".png";
    return icon;
}

// mapping of landamarks by type and icon
for (var i = 0, len = types.length; i < len; i++)
{
    landmarks[types[i]] = createIcon(types[i]);
}

the result is : { hospital : icon, church : icon, ... }

where icon is a google map icon that has an image attribute that is a string of the form "icon{type}.png" , e.g, iconhostpital.png, iconchurch.png.

To use the icons write landmarks.type where type is one the names in the array of types, e.g. landmarks.hospital.

if the image names are of the form icon + number + .png, and the number for each type is equivalent to its index in the array replace the call createIcon(type[i]) for createIcon(i).

Headwaiter answered 24/11, 2012 at 6:34 Comment(3)
Ages after I know but to clarify this code will not work as it stands and why incase anyone takes it to copy. You have not encapsulated your "for" code {} so you will just end up with the final result, which incidentally would be icon3.png because you actually wanted to append types[i] not i which is the count in the for loop.Ozalid
in the question icons are of of the form "icon" + i + ".png" = "icon1.png", you say the wanted form is "icon" + types[i] + "pgn" = "iconhostpital.png". About the not saving the the icon you are right.Headwaiter
I have not presented a full blown up solution, I was lazy. What I meant was, build the image name from the array of types, create the google icon, set the image name to the google icon image attribute and use it. no need for a variable the identifier of which is defined dynamically.Headwaiter

© 2022 - 2024 — McMap. All rights reserved.