JavaScript,检查嵌套对象属性是否为空/未定义的优雅方式

JavaScript,检查嵌套对象属性是否为空/未定义的优雅方式,javascript,object,javascript-objects,Javascript,Object,Javascript Objects,我时常遇到的一个“问题”是,我有一个对象,例如user={},在使用应用程序的过程中,这个对象会被填充。比如说,在AJAX调用之后,我会这样做: user.loc = { lat: 50, long: 9 } 在另一个地方,我想检查是否存在user.loc.lat if (user.loc.lat) { // do something } 如果它不存在,这将导致错误。如果user.loc.lat是未定义的,user.loc当然也是未定义的 "Cannot read p

我时常遇到的一个“问题”是,我有一个对象,例如
user={}
,在使用应用程序的过程中,这个对象会被填充。比如说,在AJAX调用之后,我会这样做:

user.loc = {
    lat: 50,
    long: 9
}
在另一个地方,我想检查是否存在
user.loc.lat

if (user.loc.lat) {
    // do something
}
如果它不存在,这将导致错误。如果
user.loc.lat
未定义的
user.loc
当然也是
未定义的

"Cannot read property 'lat' of null" - Dev Tools error
这意味着我需要像这样检查它:

if (user.loc) {
    if (user.loc.lat) {
        // do something
    }
}
get = function(obj, key) {
    return key.split(".").reduce(function(o, x) {
        return (typeof o == "undefined" || o === null) ? o : o[x];
    }, obj);
}

这并不是很漂亮,我的对象越大,效果就越差——很明显(想象10个嵌套级别)。 让我有点恼火的是,
if(user.loc.lat)
不仅仅返回
false
if
user.loc
也是
未定义的

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

检查这种情况的理想方法是什么?

好的,javascript有try-catch。根据您实际需要执行的操作(即,如果
语句未定义,您的
else
语句将是什么样子),这可能是您想要的

例如:

try {
   user.loc.lat.doSomething();
} catch(error) {
   //report
}

您可以使用lazy
组合检查:

if(user.loc && user.loc.lat) { ...
或者,你用咖啡脚本。ES2020有了新的语法(空合并操作符)

这将运行对
loc
属性的检查并防止空对象。

如果(user&&user.loc&&user.loc.lat){…},请尝试此


您可以使用检查null和undefined的值

如果
.loc
具有值
false
,则可以尝试

if(user&&user.loc&&typeof(user.loc)!==“未定义”){…}

如果你有一个巨大的嵌套对象,你可以看看

函数checkNested(obj/*,level1,level2,…levelN*/){
var args=Array.prototype.slice.call(参数),
obj=args.shift();
对于(变量i=0;i
更新:
尝试使用以下实用程序功能:

if (user.loc) {
    if (user.loc.lat) {
        // do something
    }
}
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
或者,仅检查属性是否存在,而不获取其值:

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

如果(user&&user.loc&&user.loc.lat){
您可以使用@AamirAfridi检查null和undefined的值,即使OP是这样写的,测试应该在最后一个对象而不是属性处停止。例如,如果
user.loc.lat
存在但有一个错误值(例如
0
),测试将返回false对不起,你们都回答得很快。这也是我想避免的一个例子。考虑到我有5到15级嵌套的巨大对象。我讨厌人们在不加评论的情况下投票。抱歉,你们的回答很快。你们的第一个方法也是我要避免的一个例子。o 15个嵌套级别。这里没有太多选项。(1)手动或使用CoffeeScript进行属性检查,(2)try/catch。如果您有一个具有15个嵌套级别的对象,并且它的属性在任何级别都可能不存在,那么我认为您的应用程序中存在一些次优设计模式。这是一个示例。我希望有一种方法可以涵盖这种情况。我显然会避免15个嵌套级别,但如果旧的服务器端应用程序只是这样做会怎么样我必须处理它?这就是为什么我想报道这个场景。我喜欢它!非常好的解决方案。get方法的问题是它可能会从链中的任何位置返回属性,它不会专门测试最后一个属性。@RobG怎么会这样?只要它碰到一个未定义的属性,它就会一路通过,结果就是未定义的。我希望LoaSug会有一个函数。<代码>。在异常情况下,您应该在不插入try-catch的情况下处理它。(当然,您可能会插入else子句)。我喜欢这种解决方案,因为简单的内容有时会因为条件而变得更难阅读。@JonasStensved指出在这个问题上不使用try-catch,因为启动异常(我认为,在编写
抛出
之前,您不会启动它)但问题可能是块中出现了其他错误,您将来将无法检测到它。@pikilon经验法则:不要将异常用于流控制。如果您的情况确实是意外的,则抛出异常。否则,将其作为任何其他代码条件处理。