In JavaScript, is there an easier way to check if a property of a property exists?

Is there an easy way to natively determine if a deep property exists within an object in JavaScript? For example, I need to access a property like this:

var myVal = appData.foo.bar.setting;

But there is a chance that either foo, foo.bar, or foo.bar.setting has not been defined yet. In Groovy, we can do something like this:

def myVal = appData?.foo?.bar?.setting

Is there a similar way to do this in JavaScript, without having to write a custom function or nested if statements? I've found this answer to be useful, but was hoping there was a more elegant and less custom way.


Solution 1:

I find this very convenient:

var myVal = (myVal=appData) && (myVal=myVal.foo) && (myVal=myVal.bar) && myVal.settings;

If a property exists, the next part of the sequence will be attempted.

When the expression before && evaluates to false, the next part of the expression will not be checked. If either of myVal.appData.foo.bar.settings is not defined, the value of myVal (undefined( will evaluate to false.

Solution 2:

Sorry, it's not great:

var myVal = appData && appData.foo && appData.foo.bar && appData.foo.bar.setting;

Another option:

try {
    var myVal = appData.foo.bar.setting;
} catch (e) {
    var myVal = undefined;
}

The . operator is not really intended for accessing objects like this. Probably using a function would be a good idea.

Solution 3:

I find other approaches a bit immense. So, what would be the major drawback of the following approach:

// Pass the path as a string, parse it, and try to traverse the chain.
Object.prototype.pathExists = function(path) {
    var members = path.split(".");
    var currentMember = this;

    for (var i = 0; i < members.length; i++) {
        // Here we need to take special care of possible method 
        // calls and arrays, but I am too lazy to write it down.
        if (currentMember.hasOwnProperty(members[i])) {
            currentMember = currentMember[members[i]];   
        } else {
            return false;
        }
    }
    return true;
}

Basically, we define a method on the object (not necessarily) and that method takes the path to a nested object and returns existence confirmation, likeappData.pathExists("foo.bar.setting");

EDIT: Check object[prop] == undefined is not semantically correct since it will return false even if the property is defined although its value is undefined; that is why I use hasOwnProperty to check is the property defined. This might not be important if one needs to just fetch the value.