最有效的Javascript方式来检查未知对象中的对象是否存在

时间:2015-08-17 03:53:31

标签: javascript performance

这是我在Javascript中经常遇到的问题。让我们说我有一个像这样的对象:

var acquaintances = {
   types: {
      friends: {
         billy: 6,
         jascinta: 44,
         john: 91
         others: ["Matt", "Phil", "Jenny", "Anna"]
      },
      coworkers: {
         matt: 1
      }
   }
}

在我的理论课程中,我所知道的只是acquaintances是一个对象;我不知道是否已设置acquaintances.types,或者是否已设置friends

如何有效检查acquaintances.types.friends.others是否存在?

我通常会做的是:

if(acquaintances.types){
  if(aquaintances.types.friends){
    if(acquaintances.types.friends.others){
       // do stuff with the "others" array here
    } 
  }
}

除了费力之外,这些嵌套的if语句有点像管理的噩梦(实际上我的对象有更多的级别!)。但是,如果我直接尝试if(acquaintances.types.friends.others){)之类的话,types还没有设置,那么程序就会崩溃。

Javascript以一种整洁,易于管理的方式执行此操作有哪些方法?

4 个答案:

答案 0 :(得分:4)

另一种方法是:

((acquaintances.types || {}).friends || {}).others

比其他解决方案短,但可能会或可能不会让您感到兴奋。

你也可以建立一个小帮手,让同样的想法变得更加美味:

function maybe(o) { return o || {}; }

现在你可以做到

maybe(maybe(acquaintances.types).friends).others

如果你不介意将属性名称写成字符串,你可以做一个小帮手:

function maybe(obj) {
  return Object.defineProperty(
    obj || {}, 
    'get', 
    { value: function(prop) { return maybe(obj[prop]); }
  );
}

现在你可以写

maybe(acquaintances.types').get('friends').others

在ES6中,你可以使用带有默认值的解构赋值,尽管是笨拙的,这样做:

var { types: { friends: { others } = {} } = {} } = acquaintances;

如果你想在表达式上下文中使用它,而不是分配给变量,理论上你可以使用参数解构:

(({ types: { friends: { others } = {} } = {} }) => others)(acquaintances)

毕竟说完了,标准方法仍然是

acquaintances.types && 
  acquaintances.types.friends && 
  acquaintances.types.friends.others

这就是为什么ES6设计组中有一个关于类似CoffeeScript的存在运算符的活动(?)discussion,但它似乎没有快速收敛。

答案 1 :(得分:3)

它在JavaScript中并不好用。

你可以将它们添加到一个大的条件......

if (obj.prop && obj.prop.someOtherProp) { }

...或者写一个辅助函数来传递一个对象和一个字符串......

var isPropSet = function(object, propPath) {
    return !! propPath.split('.')
           .reduce(function(object, prop) { return object[prop] || {}; }, object);
};

isPropSet(obj, 'prop.someOtherProp);

...或者您可以使用CoffeeScript及其?运算符...

obj.prop?.someOtherProp

你也可以将查询包装在try/catch中,但我不推荐它。

答案 2 :(得分:3)

和运算符是顺序的,因此您可以在不嵌套if语句的情况下执行此操作。

if(acquaintances.types && aquaintances.types.friends && acquaintances.types.friends.others){
    //acquaintances.types.friends.others exists!
}

答案 3 :(得分:2)

而不是:

if(acquaintances.types){
  if(aquaintances.types.friends){
    if(acquaintances.types.friends.others){
       // do stuff with the "others" array here
    } 
  }
}

试试这个:

   if(acquaintances &&
      acquaintances.types &&
      acquaintances.types.friends &&
      acquaintances.types.friends.others) {
    }

或者

acquaintances &&
acquaintances.types &&
acquaintances.types.friends &&
acquaintances.types.friends.others ?
doSomething() : doSomethingElse()