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

我经常遇到的一个“问题”是我有一个对象,例如 user = {},在使用这个应用程序的过程中,这个对象被填充了。假设在某个地方,在一个 AJAX 调用或者其他什么事情之后,我这样做:

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

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

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

如果它不存在,这将导致错误。如果 user.loc.latundefined,那么 user.loc当然也是 undefined

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

这意味着我需要像这样检查:

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

或者

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

这并不是真的很漂亮,我的对象越大,情况就越糟糕——很明显(想象一下10层嵌套)。 如果 user.loc也是 undefined,那么 if(user.loc.lat)不仅返回 false,这让我有点失望。

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

93193 次浏览

Javascript 有 try-catch。这取决于您实际需要做什么(例如,如果您的 else语句是 undefined,那么它看起来会是什么样子) ,这可能就是您想要的。

例如:

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

您可以使用惰性 and组合这些检查:

if(user.loc && user.loc.lat) { ...

或者,您可以使用 CoffeeScript。 ES2020有了新的语法(Nullish 合并运算符)。

user.loc?.lat?. '...'

它将对 loc属性进行检查,并防止出现空对象。

试试这个 if(user && user.loc && user.loc.lat) {...}

您可以使用 类型检查 null 值和未定义值

如果 .loc的值为 false,则可以尝试

if(user && user.loc && typeof(user.loc)!=="undefined"){...}

如果你有一个巨大的嵌套对象比看看

来源

function checkNested(obj /*, level1, level2, ... levelN*/) {
var args = Array.prototype.slice.call(arguments),
obj = args.shift();


for (var i = 0; i < args.length; i++) {
if (!obj.hasOwnProperty(args[i])) {
return false;
}
obj = obj[args[i]];
}
return true;
}


var test = {level1:{level2:{level3:'level3'}} };


checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false

更新: 尝试 < a href = “ https://lodash.com/docs/4.17.0 # get”rel = “ norefrer”> lodash.get

你可以像这样使用一个实用函数:

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