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.

  1. If you dislike using eval in your code, you can always do this:

    function echoVar(whichone) {
      document.write(Function("return " + whichone)());
    }
    
  2. 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.

  3. 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/

  4. 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.