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...
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.
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.
The simplest test is:
if (foo && foo.bar) {
// play with foo.bar.myVal ...
}
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;
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
}