7

How do I check whether a variable name is "in use"? Meaning: how do I check if a variable name has already been used in a var varname = 'something' statement?

Normally, I would just check if typeof varname == 'undefined', which seems to work fine. The issue is when there is an element on the page with id="varname". Now, when I check typeof varname == 'undefined', i get false regardless, because varname is some HTML element.

varname is not "in use", but it is not undefined either.

<body id="test1"></body>
<script>
    //if <body> has an id of test1, how do i check if test1 is undeclared?
    console.log(typeof test1 == 'undefined'); // the <body> element causes this to be true
    console.log(typeof test2 == 'undefined'); // outputs true as expected
</script>

Additionally, can you check for the corner case: var test1 = document.getElementById('test1') has been executed?

uber5001
  • 3,864
  • 4
  • 23
  • 44
  • possible duplicate: http://stackoverflow.com/questions/858181/how-to-check-a-not-defined-variable-in-javascript – Ray Cheng May 09 '13 at 05:08

3 Answers3

6

The only possible way to achieve what you need is through the evil eval(), as it is not possible to access local variables through their name as strings. (Globals are possible using window["variableNameAsString"].)

The solution snippet presented below has the following effect:

Returns true if varName was declared and initialized (even if with null) and is readable from the current scope. Otherwise returns false.

DEMO jsFiddle here.

Source:

function removeIdOfAllElementsWithId(id) {
    var element, elementsFound = [];
    while ((element = document.getElementById(id)) !== null) {
        element.removeAttribute('id')
        elementsFound.push(element);
    }
    return elementsFound;
}
function assignIdToElements(elements, id) {
    for (var i = 0, n = elements.length; i < n; i++) { elements[i].id = id; }
}
var isDefinedEval = '(' +
    function (isDefinedEvalVarname) {
        var isDefinedEvalResult;
        var isDefinedEvalElementsFound = removeIdOfAllElementsWithId(isDefinedEvalVarname);
        try {
            isDefinedEvalResult = eval('typeof '+isDefinedEvalVarname+' !== "undefined"');
        } catch (e) {
            isDefinedEvalResult = false;
        }
        assignIdToElements(isDefinedEvalElementsFound, isDefinedEvalVarname);
        return isDefinedEvalResult;
    }
+ ')';

Usage:

To test if a variable with name variableName is defined:

eval(isDefinedEval + '("' + 'variableName' + '")') === true

To check if it is not defined:

eval(isDefinedEval + '("' + 'variableName' + '")') === false

In the fiddle you'll find lots of unit tests demonstrating and verifying the behavior.

Tests:

  • Several tests are included in the fiddle;
  • This snippet was tested in IE7, IE8 and IE9 plus latests Chrome and Firefox.

Explanation:

The function must be used through eval() because it needs to have access to the variables locally declared.

To access such variables, a function must be declared in the same scope. That's what eval() does there: It declares the function in the local scope and then calls it with varName as argument.

Aside that, the function basically: - Removes the ID attribute of every element that has an ID === varName; - Checks if the variable is undefined; - And reassign the ID of those elements it removed the attribute.

Note: this answer was heavily edited, some coments may not be still appliable.

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
  • Cool! This seems to work. Is there any reason `eval("varname")` throws an exception as opposed to `varname`? Just curious. – uber5001 May 09 '13 at 05:10
  • Ooops. The first "false" should be "true", since `test1` is declared and therefore exists before any code is executed. It just isn't assigned a value until after the first few tests. Note that `eval('test1')` simply returns the string "test1". – RobG May 09 '13 at 05:14
  • 1
    Another good use of evil `eval` but sometimes it's necessary. – Ray Cheng May 09 '13 at 05:15
  • @uber5001 I'll try to explain: `eval()` evaluates the expression. So `eval("varname")` will throw an exception if `varname` was never defined. `eval(varname)` will not throw an exception if `varname`'s value is, for instance` `"myVar"` and there is a variable `myVar` defined. Let me know if I can explain further. – acdcjunior May 09 '13 at 05:24
  • @RobG actually, I can't while it's accepted. About your other comment, the first call of `isDefined` must be `false` according with the OP's constraints. Also `eval('test1')` returns the value of `test1`. Something like `eval('"test1"')` would return the **string** `'test1'`... – acdcjunior May 09 '13 at 13:41
  • 1
    @uber5001 I updated the answer. Check if it works for you. (Also check the tests on the fiddle, hopefully they meet your usage pattern.) – acdcjunior May 10 '13 at 00:11
  • Hi there, the function had a bug. I updated the answer. Please update your use of it if possible as well. Thanks! – acdcjunior Feb 28 '14 at 17:57
1

Not sure if this what you are looking for.

if(typeof test1 == "undefined" && document.getElementById("test1") == null) {
//There is no element with an id="test1" and a variable test1
}
c.P.u1
  • 16,664
  • 6
  • 46
  • 41
  • 1
    If `typeof test1 == "undefined"` you have no idea if the variable has been defined (declared or otherwise initialised) or not, you can only say that **if** it has been defined, it either hasn't been assigned a value, or has been assigned the *undefined* value. Nice try though. :-) – RobG May 09 '13 at 04:35
  • @Ian the comment applied to the first version, before any edit, of this answer. – acdcjunior May 09 '13 at 04:35
  • @RobG So don't they mean to have `if (typeof test1 !== "undefined" && document.getElementById("test1") == null) {` which says `test1` is defined as something, but it's not the `id` of an element. – Ian May 09 '13 at 04:38
  • You have to check with name attributes too. IE doesn't know the difference between the name and ID attributes, but other browsers do, while mimicing IE's "make globals out of names and IDs" feature. One day all browsers will drop support for this crap. One day… :-/ – RobG May 09 '13 at 08:41
  • @Ian—yes, but `typeof test1 == "undefined"` does not tell you that there is "a variable test1". While my comment was for the previous version of the answer, it's still not right. – RobG May 09 '13 at 08:51
1

In a context other than the global context in some browsers, it is impossible to reliably determine if a variable has been defined (either by being declared or otherwise initialised) or not other than using try..catch.

Therefore it's not a good strategy to need to do that.

In a global context, in non–IE browsers, you can do something like:

var global = this;

if (!global.hasOwnProperty('foo')) {
  // there is no global foo
}

but IE doesn't implement hasOwnProperty on the global object. Note that DOM element names and IDs do not overwrite the value of declared global variables.

But anyway, all this is useless since you may well have:

var foo = document.getElementById('foo');

What now?

RobG
  • 142,382
  • 31
  • 172
  • 209