JavaScript,优雅的方法来检查NULL / undefined的嵌套对象属性

问题描述:

我偶尔会遇到的问题是我有一个对象,例如 user = {} 并且在使用应用程序的过程中会填充此内容。让我们说somwhere,在AJAX调用之后或我这样做:

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
}

在另一个地方,我想检查一下 user.loc.lat 存在。

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

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

如果它不存在,这会导致错误。如果 user.loc.lat undefined user.loc 当然也是 undefined

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
    }
}

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

这不是很漂亮,我的对象越大越好 - 显然(想象10级嵌套)。
我很遗憾 if(user.loc.lat)不仅仅是返回 false 如果 user.loc 也是 undefined

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?

你可以使用这样的效用函数:

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);
}

用法:

 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')) ...