JavaScript, elegant way to check nested object properties for null/undefined

ProblemsOfSumit picture ProblemsOfSumit · May 22, 2014 · Viewed 75.5k times · Source

a "problem" which i have every now and then is that i have an object e.g. user = {} and through the course of using the app this gets populated. Let's say somwhere, after an AJAX call or something i do this:

user.loc = {
    lat: 50,
    long: 9
}

At another place i want to check if user.loc.lat exists.

if (user.loc.lat) {
    // do something
}

If it does not exists, this will cause an error. If user.loc.lat is undefined, user.loc of course is undefined as well.

"Cannot read property 'lat' of null" - Dev Tools error

That means I need to check it like this:

if (user.loc) {
    if (user.loc.lat) {
        // do something
    }
}

or

if (user.loc && user.loc.lat) {
    // do something
}

This isn't really pretty and the bigger my objects are the worse it gets - obviously (imagine 10 levels of nesting). It kind bums me that if(user.loc.lat) isn't just returning false if user.loc is undefined as well.

What's the ideal way to check situations like this?

Answer

georg picture georg · May 22, 2014

You can use an utility function like this:

get = function(obj, key) {
    return key.split(".").reduce(function(o, x) {
        return (typeof o == "undefined" || o === null) ? o : o[x];
    }, obj);
}

Usage:

 get(user, 'loc.lat')     // 50
 get(user, 'loc.foo.bar') // undefined

Or, to check only if a property exists, without getting its value:

has = function(obj, key) {
    return key.split(".").every(function(x) {
        if(typeof obj != "object" || obj === null || ! x in obj)
            return false;
        obj = obj[x];
        return true;
    });
}

if(has(user, 'loc.lat')) ...