JavaScript,一种检查嵌套对象属性是否为null/undefined的优雅方式

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

本文关键字:null 是否 undefined 方式 属性 对象 嵌套 检查 一种 JavaScript      更新时间:2023-09-26

一个"问题",我有一个对象,例如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.locundefined,那么if(user.loc.lat)不只是返回false,这有点让我恼火。

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

您可以像这样使用一个实用程序函数:

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

您可以使用lazy and:

组合检查。
if(user.loc && user.loc.lat) { ...

或者,您使用CoffeeScript。ES2020有新的语法(Nullish coalescing Operator)。

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

将运行loc属性检查和防止空对象

javascript有try-catch。这取决于你实际需要做什么(即你的else语句看起来像什么,如果它是undefined),这可能是你想要的。

的例子:

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

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

可以使用typeof

检查null和undefined的值

如果.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

更新:尝试lodash.get