Trying to avoid eval getting array element from window object-Collection of common programming errors
I’ve got a function that wants to access a global variable, the name of which arrives as a string argument. This is how it looks now, using eval:
function echoVar(whichone){
document.write(eval(whichone));
}
I thought I’d just use the window[] syntax and have this:
function echoVar(whichone) {
document.write(window[whichone]);
}
If I create a var and call it like this, it doc writes ABC as expected:
var abc = "ABC";
echoVar("abc");
If the var I want to access is an array element though, it doesn’t work:
var def = ["DEF"];
echoVar("def[0]"); //fails with undefined
Obviously that’s actually executing window[def[0]] which rightly gives undefined (because there’s no variable called DEF). What I actually want to happen is that it executes window[“def”][0].
The only way I know to achieve this, is to do a split on the whichone parameter with “[” as the delimiter and then use the split [0] as the window index and a parseInt on split [1] to get the index, like this:
function echoVar(whichone){
if(whichone.indexOf("[")==-1){
document.write(window[whichone]);
}
else{
var s = whichone.split("[");
var nam = s[0];
var idx = parseInt(s[1]);
document.write( window[nam][idx] );
}
}
Am I overlooking something obvious? I’d rather keep the eval than have to do all that.
-
If you dislike using eval in your code, you can always do this:
function echoVar(whichone) { document.write(Function("return " + whichone)()); }
-
Unless this is some sick experiment, you should never be writing Javascript code that looks like this. This is terrible; you need to re-think your design. I know this isn’t what you’re looking for, but it’s the right answer.
-
The fact is you’ve got a piece of a javscript expression in a string so you either have to parse it yourself or use eval to parse it for you unless you change the way it’s passed like this:
function echoVar(a,b) { var x = window[a]; if (b) { x = x[b]; } document.write(x); }
And, then you can pass it differently like this:
var def = ["DEF"]; echoVar("def", 0); // def[0]
You could even make this support multiple dimensions if you needed to.
function echoVar(a) { var x = window[a]; for (var i = 1; i < arguments.length; i++) { x = x[arguments[i]]; } document.write(x); } var def = {myObject: {length: 3}} echoVar("def", "myObject", "length"); // def["myObject"]["length"] or def.myObject.length
You can see it work here: http://jsfiddle.net/jfriend00/dANwq/
-
It would be simpler to lose the brackets and call the item with dot notation
function reval(s, O){ s= String(s); O= O || window; var N= s.split("."); while(O && N.length) O= O[N.shift()]; return O || s; } window.def= ['definition']; alert(reval('def.0')) /* returned value: (String) definition */
Originally posted 2013-11-09 19:45:29.