用于检查属性是否存在的简写函数

时间:2011-07-04 12:32:28

标签: javascript jquery function properties exists

你能帮助我做一个简写函数来判断对象属性是否存在吗?在99%的情况下,我想用它来检查返回的json对象是否包含指定的属性。请注意,无法保证必须定义任何父属性甚至json对象本身。

我正在以这种方式思考:

function propertyExists(<property>) {
    // property is something like data.property.property
    return typeof(data) !== "undefined" && typeof(data.property) !== "undefined" && typeof(data.property.property) !== "undefined";
}

我不知道如何以动态方式编写它以检查所有父属性。 in-parameter也应该只是对“data.property.property”的引用,而不是字符串,所以我不知道如何在其中找到父属性。

3 个答案:

答案 0 :(得分:4)

这是我从一个项目中找到的函数,它告诉你是否定义了一个属性(包括它的所有父属性,如果有的话):

function isDefined(target, path) {
    if (typeof target != 'object' || target == null) {
        return false;
    }

    var parts = path.split('.');

    while(parts.length) {
        var branch = parts.shift();
        if (!(branch in target)) {
            return false;
        }

        target = target[branch];
    }

    return true;
}

它应该像这样使用:

var data = { foo: { bar: 42 } };
isDefined(data, "foo"); // true
isDefined(data, "foo.bar"); // true
isDefined(data, "notfoo"); // false
isDefined(data, "foo.baz"); // false

您可以轻松调整此值以返回值本身(或null),而不是true / false

更新:在阅读了有关该问题的评论后,我搜索了Javascript in运算符,并将typeof测试替换为该值。现在,代码写成“它的意图是什么”。

答案 1 :(得分:2)

允许JSON属性包含{"a.b": 42}中的点,这使得点串不适合对象的“深度引用”。

isDefined({"a.b": 42}, 'a.b') // false
isDefined({"a": 42}, 'a.b') // TypeError

因此,数组可能是参考或索引的更好选择

function hasProperty(value, index) {
    if (index instanceof Array) {
        return index.length === 0 ||
            (hasProperty(value, index[0])
                && hasProperty(value[index[0]], index.slice(1)));
    }
    return value.hasOwnProperty(index);
}

它的用法如下:

hasProperty(42, []); // true
hasProperty(42, ['a']); // false
hasProperty(42, ['a']); // false
hasProperty({a: 42}, 'a'); // true
hasProperty({a: 42}, ['a']); // true
hasProperty({a: 42}, ['a', 'b']); // false
hasProperty({a: {b: 42}}, ['a', 'b']); // true
hasProperty({"a.b": 42}, ['a.b']); // true
hasProperty([1,2,3], 2); // true
hasProperty([1,2,3], 3); // false
hasProperty({a: {b: [1,2,3]}}, ['a', 'b', 2]); // true

请注意,由于使用了原型函数hasPropertyhasOwnProperty会忽略原型中的属性。

答案 2 :(得分:1)

我目前无法找到其他帖子,请确保以下内容正确:

function checkAccess(obj, path) {
  var path = path.split('.');
  var prop;

  for (var i=0, iLen=path.length; i<iLen; i++) {
    if (obj !== null && typeof obj == 'object') {
      prop = path[i];

      if (prop in obj) {
        obj = obj[prop];
      }
    } else {
      return false
    }
  }
  return true;
}

var o = {foo:{bar:null}};

alert(checkAccess(o, 'foo.bar')); // true
alert(checkAccess(o, 'foo.bar.baz')); // false

请注意,这应该适用于JSON,但如果涉及到主机对象,则所有投注均已关闭,因为 typeof 无法保证返回 object (或任何内容)那种情况。如果您需要测试主机对象,可能try..catch可能是最强大的解决方案,除非您确信正在测试的对象将返回预期结果。

try {
  alert( o.foo.bar.baz);
} catch(e) {
  alert( 'oops');
}

如果你想使用单个参数,那么我将假设基础对象是一个全局属性:

var checkAccess = (function(global) {
  return function (expr) {
    var path = expr.split('.');
    var obj, prop;

    if (path.length) {
      obj = global[path.shift()];

      for (var i=0, iLen=path.length; i<iLen; i++) {
        if (obj !== null && typeof obj == 'object') {
          prop = path[i];

          if (prop in obj) {
            obj = obj[prop];
          }
        } else {
          return false
        }
      }
      return true;
    }
    return false;
  }
}(this));

修改

请注意,上述内容只是意味着尝试访问路径不会返回错误,并不意味着它将返回一个值(可能是未定义的,null或其他内容)。

相关问题