1

Is there a way to do the following without using eval()?

The following function accepts an array of strings where the strings are object names. I iterate over them to ensure that none of them are undefined. I'd like to be able to do this without using eval()

function hasMissingDependencies(dependencies) {
    var missingDependencies = [];

    for (var i = 0; i < dependencies.length; i++) {
        if (eval('typeof ' + dependencies[i]) === 'undefined') {
            missingDependencies.push(dependencies[i]);
        }
    }

    if (missingDependencies.length > 0) {
        return true;
    }

    return false;
}

With this, I'm able to pass something like the following and get what I want:

alert(hasMissingDependencies(['App.FooObject', 'App.BarObject']));

I'd prefer to not use eval() but haven't found another way to check if an object is undefined when the object names are passed as strings.

Jared
  • 4,567
  • 2
  • 26
  • 30
  • why do you need to pass them as strings? – Ben McCormick Apr 09 '13 at 19:04
  • I'm unaware of another way to pass object names that **may** be undefined to another function. For example, calling `hasMissingDependencies(App.FooObject, App.BarObject)` throws an error before ever making it into the function if either of those objects are not defined. Am I missing something? – Jared Apr 09 '13 at 19:11
  • where are you passing it from? You can see my answer for a possible solution, but it would be much simpler to check if they exist BEFORE you pass them, and then pass null or some other value if not. – Ben McCormick Apr 09 '13 at 19:13
  • If `App` is `undefined` or `null`, then yes, it would throw an error because you're trying to dereference a null reference. But if `App` is not `undefined` or `null`, then you can pass those two arguments and then just check if they are `undefined` in the function, which would be checking if the `FooObject` and `BarObject` properties exist on the `App` object. – ajp15243 Apr 09 '13 at 19:14
  • @ben336 My use case is that I'm creating "modules" that can be used by other developers in our application. This function is used to ensure that the modules that the current one depends on are included on the page. So to make it "easy", each module defines a list of dependencies and calls this function. Ideally we'd be using something like RequireJS for this, but for reasons I won't get into it's unlikely this will change. – Jared Apr 09 '13 at 19:17
  • @ajp15243 These are just an example. Throughout the application, these can be `App.sublevel.Foo` (an unknown depth and no guarantee that all sublevels exist at any given time). – Jared Apr 09 '13 at 19:19
  • Combine [Javascript dynamic variable name](http://stackoverflow.com/questions/5117127/javascript-dynamic-variable-name) with any of [these](http://stackoverflow.com/a/14397052/1048572) – Bergi Apr 09 '13 at 19:19

2 Answers2

5

Assuming that these are global variables (IE not defined within an inner function scope), you could split on periods and use bracket notation.

something like

function isDefined(name, obj){
   if(!obj){
      obj = window;
   }
   var pathArr = name.split(".");
   obj = obj[pathArr.splice(0,1)];
   if(typeof obj !== undefined){

     return pathArr.length ? isDefined(pathArr.join("."),obj): true;
   }

   return false;


}

Note that unless you're trying to write a requireJS replacement, this is pretty much always a bad idea though. Check if the values exist in the context you're calling the function, and then pass in the values if they exist or null/undefined/some default value otherwise. If you don't control the passing context, ask for objects and then check to see if they're defined.

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71
  • Noted. Thanks for the help. I'm going to mark this answer as accepted since it's the easiest to follow, but I encourage anyone using this thread to look at the answer @dystroy for a more concise version of this. – Jared Apr 09 '13 at 19:33
2

You seem to want to check if global variables whose names are in your array are defined.

You can build a simple function to get those variable :

function getVar(name) {
   var v = window, path=name.split('.');
   while (path.length>0 && v) v = v[path.shift()];
   return v;
}

which would allow you to test

if (typeof getVar(dependencies[i]) === 'undefined')
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758