How to check if object within object exists

2019-02-22 04:18发布

问题:

It seems that the following technique for checking the existence of an object member produces an error because the 'bar' parent object hasn't been declared before the check, which means I either have to declare it before the check or use two 'typeof' expressions, either of which would be excess code:

var foo = {},
    newVal = (typeof foo.bar.myVal !== 'undefined' ? foo.bar.myVal : null );

Error: foo.bar is undefined

So, how do you check if a member within an undeclared object exists without producing an error?

I love javascript, but sometimes...

回答1:

It can be done simply using the code below:

var newVal = (foo && foo.bar && typeof foo.bar.myVal !== 'undefined') ? foo.bar.myVal : foo.bar.myVal

A property is null or undefined, it will be evaluated as false so the above code will only process up to the first 'false' statement.



回答2:

var newVal = ('foo' in window && // could be typeof foo !== 'undefined' if you want all scopes
             'bar' in foo &&
             'myVal' in foo.bar) ? foo.bar.myVal : null;

To be fair to javascript, that reads almost like natural language.



回答3:

The simplest test is:

if (foo && foo.bar) {
  // play with foo.bar.myVal  ... 
}


回答4:

You could wrap it up into a method:

function checkGraph(obj, graphPath)
{
  var parts = graphPath.split(".");
  var root = obj;

  for (var i = 0; i < parts.length; i++)
  {
    var part = parts[i];
    if (root[part] && root.hasOwnProperty(part))
      root = root[part];
    else
      return false;
  }

  return true;
}

Where you could call it as:

var foo = {},
    newVal = checkGraph(foo, "bar.myVal") ? foo.bar.myVal : null;


回答5:

As Matthew Abbott gave in his response, you can write a method for it to use it later if you do a lot of diving into child properties where the whole object or somewhere along the chain can be null. Below is my implementation using lodash.

checkGraph(obj, graphPath) {
    if (obj) {
      let root = obj;
      _.each(graphPath.split('.'), part => {
        if (root[part]) {
          root = root[part];
        } else {
          return false; // bad property
        }
      });
      return true;
    }
    return false; // bad object
  }

You can call the method like this:

if (this.checkGraph(object, 'property.subproperty') {
    // do thing
}