0

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.

3
  • Is there no way to have the value passed in a nicer way? Commented Dec 2, 2011 at 0:46
  • Is this an experiment or you are trying to use this technique for production use? Commented Dec 2, 2011 at 0:48
  • I'm using a library (like jquery but not jquery) and it happens to pass me the name of the var in this way. Sadly I can't change what I receive, only how I use it. Commented Dec 2, 2011 at 7:17

4 Answers 4

1

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

function echoVar(whichone) {
  document.write(Function("return " + whichone)());
}
Sign up to request clarification or add additional context in comments.

3 Comments

I maybe wrong but isn't that using eval behind the scenes? It's hard to imagine how that would execute without it. Rather like document.write(23) is using .toString() even though you can't see it there.
Well, not really. There are posts out there explaining the differences between eval and Function. By the way, 23 has no toString method to call. If you don't trust me just try var x = 23; x.toString = function () { return "69"; }; document.write(x);. Now replace the first statement with var x = Object(23); and you'll see the difference.
I like it. I've adopted this method :)
0

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.

1 Comment

It's true. I don't have control over the design though.
0

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/

2 Comments

Then, you have to parse it yourself or use eval() - your choice. As long as this isn't end-user supplied strings, I see no issues with just using eval().
That's the conclusion I came to myself too, either use eval or bloat it with half a dozen lines of code. I figured I'd come here though and see if there was a clever solution I just wasn't aware of.
0

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
*/

1 Comment

Only slightly simpler, it just means I don't have a trailing ], which parseInt ignores anyway. Besides, I'm not in control of the call format, otherwise I'd have redesigned it completely and made it pass the object itself rather than a string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.