1

I'm having trouble figuring out how I can take a string of an object name and check if that object actually exists.

What I'm trying to accomplish is have an array the defines the required objects for a particular JavaScript "module" to work, for instance:

var requiredImports = ['MyApp.Object1', 'MyApp.Object2'];

Then using requiredImports, I want to loop over them and check if the are defined. Without using the above array, I can do the following which is what I'm trying to accomplish:

if (MyApp.Object1 == undefined) {
    alert('Missing MyApp.Object1');
}

But using the above, I'd have to hard code this for every module rather than making a generic method that I can just pass it an array of strings and have it effectively do the same check for me.

I tried doing this by just passing it the objects themselves such as:

var requiredImports = [MyApp.Object1, MyApp.Object2];

But that throws a JavaScript error when those objects do not exist, which is what I'm trying to catch.

1
  • Here is essentially what I ended up with by using ExtJS to handle the forEach in the response from @Yoshi jsfiddle.net/jaredhocutt/c5fM6/4 Commented Nov 29, 2011 at 16:56

5 Answers 5

3
var MyApp = {
  Object1: {}
};

function exists(varName, scope) {
  var parent = scope || window;
  try {
    varName.split('.').forEach(function (name) {
      if (parent[name] === undefined) {
        throw 'undefined';
      }

      parent = parent[name];
    });
  }
  catch (ex) {
    return false;
  }

  return true;
}

console.log(
  exists('MyApp.Object1'),   // true
  exists('MyApp.Object2'),   // false
  exists('window'),          // true
  exists('document'),        // true
  exists('window.document')  // true
);


// or
console.log(
  ['MyApp.Object1', 'MyApp.Object2', 'window', 'document', 'window.document'].filter(function (varName) {
    return !exists(varName);
  })
);
// => ["MyApp.Object2"]

Note: that forEach is ES5 and as such not implemented in some browsers. But if you'd go with this solution, there is a nice polyfill here.

Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly what I'm looking for! Very clean and easy to understand. The app that I'm working on uses the ExtJS framework, so I'm able to safely use Ext.each() to attain the same result as forEach. Thank you very much for your help!
3

You can check for definedness with

if ( typeof window['MyApp'] === 'undefined' || 
     typeof window['MyApp']['Object1'] === 'undefined' ) 
{
    alert('Missing MyApp.Object1');
}

and so on.

5 Comments

Why so much code? if (!(window.MyApp && window.MyApp.Object1)) { ... would do the same thing.
@Yoshi: It's a devops_borat way of improving your metrics. Anyhow, you're totally right - I guess I was deciding between typeof MyApp... and window.MyApp... and chose both.
@Yoshi: I think you didn't read the question properly. 'MyApp.Object1' is string, so how you going to do window.MyApp? IMO this answer is perfect. +1 to the answer.
@BheshGurung from Jareds last example (var requiredImports = [MyApp.Object1, MyApp.Object2];) I guessed he would or could also be willing to use that syntax.
@Yoshi: That's something he tried and didn't work. You know you can't use something that you yet need to figure whether it's defined or not.
2

Assuming MyApp.Object1 is a global scope, window is the parent object and since that is the top level object, you don't need to prefix your global vars with it. So window.MyApp.Object1 is the same as MyApp.Object1 (again, assuming this is within global scope).

Also, in javascript, MyApp['Object1'] is the same as MyApp.Object1. So if we apply this principle to the main window object, you can check for window['MyApp'] or window['MyApp']['Object1'] and the key here is that you can replace 'MyApp' and 'Object1' with a variable.

Example:

/* check if a variable/object exists in the global scope) */
function checkIfExists(someVar) {
  if (typeof(window[someVar]) == 'undefined')
    return true;
  return false;
}

var foo = 'bar';
alert(checkIfExists('foo'));

Comments

1

You can evaluate your custom expression in JavaScript. Consider the code below:

var MyApp = {
  Object1: "foo",
  Object2: "bar"
};

var IsExists = function(varName) {
    return new Function('return typeof(' + varName + ') === "undefined" ? false : true;')();
};

USAGE

var requiredImports = ['MyApp.Object1', 'MyApp.Object2'];

for (var i = 0; i < requiredImports.length; i++)
{
    alert(requiredImports[i] + ": " + IsExists(requiredImports[i]))
}

Comments

0

You only get error for first level (MyApp in your example). I assume you have only a few first-level requires, so check them manually by window[x] which does not throw:

var requiredTopLevel = ['MyApp'];
for (var i = 0; i < requiredTopLevel.length; ++i) {
  if ("undefined" === typeof window[requiredTopLevel[i]]) {
    // problem with requiredTopLevel[i]
  }
}

and then, to check nested requires (if top-level is present) you can use the values without fear. For example this will work:

var requiredNested = { 'Object1':MyApp.Object1, 'Object2':Myapp.Object2 };
for (var name in requiredNested) {
  if ("undefined" === typeof requiredNested[name]) {
    // problem with name
  }
}

Comments

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.