0

I know if you want to check if a variable a is defined you can do this

if (typeof a !== 'undefined') {
    // the variable is defined
}

but what if you want to make a function out of it, like this

function checkDefined(name) {
    return typeof name !== 'undefined';
}
checkDefined("a");

this wouldn't work, but how can I get it to work if I have to pass a string version of the variable name?

Thanks

Abhi
  • 4,123
  • 6
  • 45
  • 77
omega
  • 40,311
  • 81
  • 251
  • 474
  • 2
    You cannot do that for local variables. What problem are you trying to solve? – SLaks Sep 08 '17 at 14:48
  • 2
    Any time you find yourself using variable variables, you should be using an object instead. – Barmar Sep 08 '17 at 14:49
  • 1
    For global variables you can use `window[name]` – Barmar Sep 08 '17 at 14:50
  • In my case, I only have a string of the variable name I want to check if defined or not. – omega Sep 08 '17 at 14:50
  • 1
    http://xyproblem.info – SLaks Sep 08 '17 at 14:51
  • return `eval("typeof " + name) !== 'undefined'` – Abhi Sep 08 '17 at 14:53
  • @Barmar Should be noted that undefined is a valid value for a variable to hold, so window[name] could possibly return an undefined value which the variable stores. A try/catch would be most effective or .hasOwnProperty(). – Adrian Sep 08 '17 at 14:54
  • @omega Use an object instead. What do the variables represent; what do they have in common? Group variables logically into objects, then you can use `someObject.variable` or `someObject[variableName]` and check their existence with `someObject.hasOwnProperty(variableName)`. Or use [`Map`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map). – Sebastian Simon Sep 08 '17 at 14:55
  • @Adriani6 Doesn't the original `typeof a != 'undefined'` suffer from the same problem? – Barmar Sep 08 '17 at 14:55
  • @Barmar It does indeed. – Adrian Sep 08 '17 at 14:56

4 Answers4

1

Checking in global scope(window):

var a = 'test';
var b = function() {};

function checkDefined(name) {
    return typeof this[name] !== 'undefined';
}

console.log(checkDefined("a"));
console.log(checkDefined("b"));
console.log(checkDefined("c"));

If you want check if variable or function is declared in class object you should pass new context to checkDefined method:

    function MyCustomClass() {
        this.c = 'test';
    }

    function checkDefined(name) {
        return typeof this[name] !== 'undefined';
    }

    // Create new object of type MyCustomClass
    var myCustomClassObject = new MyCustomClass();

    // In this way you can check if variable/function is defined in object
    console.log(checkDefined.apply(myCustomClassObject, ["a"]));
    console.log(checkDefined.apply(myCustomClassObject, ["b"]));
    console.log(checkDefined.apply(myCustomClassObject, ["c"]));

apply will call a function immediately letting you specify both the value of this and any arguments the function will receive

Krzysztof Raciniewski
  • 4,735
  • 3
  • 21
  • 42
  • Can you explain your answer instead of just posting code? Why use `this` when the function isn't an object property? – Barmar Sep 08 '17 at 14:57
  • `this` is needed for checking definitions in objects. If you call `this` in global scope then it's refered to window, if you call `this` in class object - in this case `MyCustomClass` - it refers to `MyCustomClass object context` – Krzysztof Raciniewski Sep 08 '17 at 19:00
1

Inspired by this answer. I think you can try to return with eval:

function checkDefined(name) {
  return eval("typeof " + name) !== 'undefined';
}

Example:

var a = 1;

checkDefined("a") // true
checkDefined(a) // true
checkDefined("b") // false
Abhi
  • 4,123
  • 6
  • 45
  • 77
0

You should also pass on which object context you need to check if the variable is defined or not. If it's global pass the window object

function checkDefined(name, ref) {
    if(!ref) {
      ref = window;
    }
    return !!ref[name]
}


checkDefined("a"); //false if already not defined


var obj = { a: 1, b:2};
checkDefined("a",obj);//true
Vijay
  • 286
  • 1
  • 9
0

Local variables are properties of the currently scoped this object.

const log = output => document.querySelector('pre')
  .innerText += output + '\n'
  

/* In this example, running in the browser, `this` points to `window`, but 
   in other environments would still point to whatever is the global object.
   Bind `this` to the ``checkDefined` so to ensure it keeps the same value
   as where you are calling from. */

const checkDefined = function chkDef(v) {
  return typeof this[v] !== 'undefined'
}.bind(this)

a = 5

log(checkDefined('a'))
log(checkDefined('b'))

/* This is the same basic idea, but we make it a little more portable by
   not binding until right before we use it, so `this` has the correct
   scope. */


unboundCheckDefined = function chkDef(v) {
  return typeof this[v] !== 'undefined'
}
newScope()

function newScope() {
  c = 5
  const checkDefined = 
    unboundCheckDefined.bind(this)
    
  log(checkDefined('a'))
  log(checkDefined('b'))
  log(checkDefined('c'))
}
<pre></pre>
skylize
  • 1,401
  • 1
  • 9
  • 21