【问题标题】:How to check if object structure exists?如何检查对象结构是否存在?
【发布时间】:2014-09-15 11:06:14
【问题描述】:

假设我从第 3 方来源解析 JSON 对象:

var myObject = {
  person_list: [
    { black_hair: {
      list: [
        'bob',
        'john',
        'allen'
      ]}
    }
  ]
};

但是如果结构突然改变或者数据响应可能损坏,我如何检查结构的深度部分是否存在?

我可以的

if ( myObject.person_list.black_hair.list !== undefined ) {
  // do stuff
}

但在某些情况下,black_hair 可能不存在。如果对象中缺少它,那么我会得到一个Uncaught TypeError: Cannot read property 'list' of undefined。所以我能想到的检查整个结构是否完整的唯一方法是检查每个级别是否已定义:

if ( myObject.person_list !== undefined ) {
  if ( myObject.person_list.black_hair !== undefined ) {
    if ( myObject.person_list.black_hair.list !== undefined ) {
      // do stuff
    }
  }
}

但这有点荒谬。有没有一种简单的方法可以在 JavaScript 中处理这个问题?是尝试,抓住最好的方法吗?

【问题讨论】:

  • 你试过这个if(myObject && myObject.peson_list && myObject.peson_list.black_hair && myObject.peson_list.black_hair.list){}
  • 你能用 jQuery.extend() 创建一个基层对象吗?这些值可能是空的,但至少它们不会是未定义的。这取决于您期望 myObject 有多大
  • 其实你并不期望结构被破坏。所以我想说这是何时使用try-catch 语句的典型案例。否则你会检查太多的东西,可能你会忽略一些东西。如果person_list 不是undefined 而是null 会怎样?
  • 这个问题是有缺陷的,因为myObject.person_list.black_hair.list 的给定结构是未定义的,因为black_hair 不是person_list 的属性。而是对象的属性,它是person_list 数组中的第一个元素,因此该对象的实际“结构”是myObject.person_list[0].black_hair.list,因此如果测试@ 的结构,到目前为止给出的答案将正确产生false 987654337@
  • @chiliNUT 好点!我已经更新了我的答案。

标签: javascript json javascript-objects


【解决方案1】:

您可以定义一个函数来为您检查完整的结构:

function defined_structure(obj, attrs) {

    var tmp = obj;

    for(i=0; i<attrs.length; ++i) {
        if(tmp[attrs[i]] == undefined)
            return false;
        tmp = tmp[attrs[i]];
    }

    return true;
}

//...

if(defined_structure(myObject, ['person_list', 0, 'black_hair', 'list']) {
    // Do stuff
}

第一个参数是要检查结构的对象,第二个参数是一个带有嵌套属性名称的数组。

更新:

正如@chiliNUT 所指出的,person_list 是一个数组。无论如何,这种方法通过添加您要检查的项目的索引来工作(即['person_list', 0, 'black_hair', 'list'])。

【讨论】:

    【解决方案2】:

    你可以使用我写的这个函数来检查属性是否被设置。您只需要将路径作为字符串传递给属性。

    // Check if nested object properties exist on unlimited levels
    // param: str 'obj.property.property'
    function isset (property)
    {
        // split path to object property
        var properties = property.split('.');
        var obj = this;
    
        //loop through each portion of the path checking if it exists
        for (var i = 0; i < properties.length; i++)
        {
            var current_property = properties[i];
            var next_property = i < properties.length - 1 ? true : false;
    
            // IF current property exists then we need to check the next level
            if (obj[current_property] !== null && typeof obj[current_property] === 'object' && next_property)
            {
                obj = obj[current_property];
                continue;
            }
            return obj.hasOwnProperty(current_property);
        }
    }
    
    if ( isset('myObject.person_list.black_hair.list')) {
        // do stuff
    }
    

    【讨论】:

      【解决方案3】:

      使用映射预期格式的 meta 对象的方式更好

      var meta = {
          name: "person_list",
          type: [],
          component: [{
              name: 'black_hair',
              type: {},
              component: {
                  name: 'list',
                  type: []
              }
          }]
      };
      
      var myObject = {
          person_list: [{
              asdfa: {
                  list: [
                      'bob',
                      'john',
                      'allen']
              }
          }]
      };
      
      function defined(meta, obj) {
          if (meta.name == 'list' && obj[meta.name] && obj[meta.name].length) {
              return true;
          }
          if (!obj[meta.name]) {
              return false;
          };
          if (Object.prototype.toString.call(meta.type) === '[object Array]' && !obj[meta.name].length) {
              return false;
          } else if (Object.prototype.toString.call(meta.type) === '[object Array]' && obj[meta.name].length) {
              for (index in obj[meta.name]) {
                  return defined(meta.component[index], obj[meta.name][index]);
              }
          } else if (Object.prototype.toString.call(meta.type) === '[object Object]') {
              return defined(meta.component, obj[meta.name]);
          }
      }
      
      console.log(defined(meta, myObject));
      

      DEMO

      【讨论】:

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