【问题标题】:How to check if object within object exists如何检查对象中的对象是否存在
【发布时间】:2019-05-24 02:52:23
【问题描述】:

似乎以下用于检查对象成员是否存在的技术会产生错误,因为在检查之前尚未声明“bar”父对象,这意味着我必须在检查之前声明它或使用两个'typeof' 表达式,其中任何一个都是多余的代码:

var foo = {},
    newVal = (typeof foo.bar.myVal !== 'undefined' ? foo.bar.myVal : null );

Error: foo.bar is undefined

那么,如何检查未声明对象中的成员是否存在而不产生错误?

我喜欢 javascript,但有时...

【问题讨论】:

  • 请不要在您的主题行中添加标签。

标签: javascript object member literals


【解决方案1】:

只需使用以下代码即可完成:

var newVal = (foo && foo.bar && typeof foo.bar.myVal !== 'undefined') ? foo.bar.myVal : foo.bar.myVal

一个属性为空或未定义,它会被评估为假,所以上面的代码只会处理到第一个'假'语句。

【讨论】:

  • 这似乎是 JavaScript 的失败之一。我们应该能够检查对象子对象的存在,而不必首先检查父对象的存在。
  • 如果您确定父母始终存在,则可以做出这样的假设。就个人而言,如果我将对象作为参数传递,我总是会检查该对象是否有效。
  • 这根本不简单。一旦您手动错误地检查返回变量,可能来自远程主机 API,您可能会崩溃您的应用程序。
【解决方案2】:
var newVal = ('foo' in window && // could be typeof foo !== 'undefined' if you want all scopes
             'bar' in foo &&
             'myVal' in foo.bar) ? foo.bar.myVal : null;

公平地说,javascript 读起来几乎像自然语言。

【讨论】:

  • 我会在条件周围添加括号。尽管运算符优先级可能没问题,但使用括号更明显。
  • @ThiefMaster,我添加了它们。不过我不喜欢他们。 IMO 它看起来不那么明显。嗯,我会离开他们的。
【解决方案3】:

最简单的测试是:

if (foo && foo.bar) {
  // play with foo.bar.myVal  ... 
}

【讨论】:

  • 没有更好的方法...例如,如果您只输入 if (foo) ,您可以轻松检查对象 foo 是否存在,但是如果您想检查 if (foo.a.b),浏览器无法判断 a 是否存在然后 b 也不存在。
  • 这很重要,因为如果我有像 a.b.c.d.e 这样的对象并且我想检查 e 是否存在,我真的不得不为 && 发疯
  • @MuhammadUmer — 不幸的是,语言规范规定尝试访问不存在对象的属性(尝试访问 undefined 的属性)必须引发错误。您可以将其包装在 try..catch 中,但这不是一种好的做法,会影响性能,并且可能比使用 && 的代码更多。
  • 这真的很痛苦,例如,如果我从服务器获取 json,它可能包含复杂的错误消息或复杂的数据。错误消息可能如下所示:data.client.a.error.msg 或数据:data.client.oauth.about.user.name
  • 你知道其他方式吗:stackoverflow.com/a/56261366/334963
【解决方案4】:

你可以把它包装成一个方法:

function checkGraph(obj, graphPath)
{
  var parts = graphPath.split(".");
  var root = obj;

  for (var i = 0; i < parts.length; i++)
  {
    var part = parts[i];
    if (root[part] && root.hasOwnProperty(part))
      root = root[part];
    else
      return false;
  }

  return true;
}

你可以这样称呼它:

var foo = {},
    newVal = checkGraph(foo, "bar.myVal") ? foo.bar.myVal : null;

【讨论】:

  • 是的,这是唯一的方法。否则它一点也不简单。
【解决方案5】:

正如Matthew Abbott 在他的回复中给出的那样,如果您对整个对象或链上某处可能为空的子属性进行大量深入研究,您可以编写一个方法供它稍后使用。下面是我使用lodash 的实现。

checkGraph(obj, graphPath) {
    if (obj) {
      let root = obj;
      _.each(graphPath.split('.'), part => {
        if (root[part]) {
          root = root[part];
        } else {
          return false; // bad property
        }
      });
      return true;
    }
    return false; // bad object
  }

你可以这样调用方法:

if (this.checkGraph(object, 'property.subproperty') {
    // do thing
}

【讨论】:

    【解决方案6】:

    还有另一种方法是使用 JS 转译器,例如 Babel

    if (foo?.bar) {
      // play with foo.bar.myVal  ... 
    }
    

    【讨论】:

    猜你喜欢
    • 2011-09-26
    • 2016-04-02
    • 2013-09-26
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    • 2012-07-27
    • 2017-10-13
    • 1970-01-01
    相关资源
    最近更新 更多