【问题标题】:Check if a js object's properties are all null except for 3检查一个js对象的属性是否除了3之外都为null
【发布时间】:2013-05-30 06:03:15
【问题描述】:

我有一个具有 50 个属性的 js 对象。我想检查除“a1”、“a2”和“a3”之外的所有 47 个是否为空。

myObject = { 
a1: 'dont-care'
a2: 'dont-care'
a3: 'dont-care'
a4: 'am i null?'
a5: 'am i null?'
...
a50: 'am i null?'
}

【问题讨论】:

  • 考虑一个 array 用于 ordered 序列。发布的答案要求有一些键的顺序(例如发布的)并且不会在一般情况下工作,因为键/属性没有排序:如果值表示有序序列,那么数组几乎总是更合适。如果使用数组x.slice(3).every(function (v) { return v !== null }(或适当的条件),使用Array.sliceArray.every 编写也非常简单。
  • @user2246674:我的回答不需要任何键排序。
  • @CrazyTrain 嗯,我认为这个问题明确要求“前 3 个”(但我想它不是..)。您的方法在这种性质上确实很灵活。

标签: javascript arrays oop enumeration


【解决方案1】:

其他人所说的对象属性无序是完全正确的,所以“前三个”的概念是没有意义的。

因此,您可能需要一个函数,该函数可以传递一个对象和一个属性名称列表,然后检查列表中的属性以外的任何属性是否为null

请注意,我使用了=== null,所以值必须是null,而不仅仅是undefined

function allButThreeNull(obj, names) {
  for (var p in obj) {
    if (obj.hasOwnProperty(p) && names.indexOf(p) == -1) {
      if (obj[p] !== null) return false;
    }
  }
  return true;
}

var obj = {one: 'one', two: 'two', three: 'three', four: null, fiv: null};

alert(allButThreeNull(obj, 'one two three'.split(' '))); // true

请注意,在不兼容 ES5 的浏览器(例如 IE 8)中,您需要 shim for Array.prototype.indexOf

【讨论】:

    【解决方案2】:

    这个怎么样:

    var allButFirstThreeAreNull = true;
    for (var i = 4; i <= 50; i++) {
      if (myObject['a' + i] !== null) {
        allButFirstThreeAreNull = false; 
        break;
      }
    }
    

    这里的关键点是在使用括号表示法 (object[property_expression]) 时能够通过一些复杂的表达式来处理属性。而且,当然,如果您发现不等于 null 的属性,则无需检查其他属性;因此使用break


    现在事实证明,这些属性是动态的。好吧,只有一件事可以做到:

    var i, l, isValid = true, props = Object.keys(myObject);
    for (i = 3, l = props.length; i < l; i++) {
      if (myObject[ props[i] ] !== null) {
        isValid = false;
        break;
      }
    }
    

    ...除了您的前三个属性实际上可能不是您考虑的属性。检查这个,例如:

    var foo = {
      '12': null,
      booya: 3
      '2': null,
      '3': null,
    };
    

    记录其中的 Object.keys 将为您提供["2", "3", "12", "booya"],将数字属性放在前面(并按数字排序)。

    【讨论】:

    • 太棒了,现在有一个相当于“array.forEach”的对象吗?一直没找到,但依稀记得看过一本。
    • 实际上我没有在问题中指定这个,但我的属性有实际名称而不是 a1 - a50。如何在此循环中访问该密钥?
    • 你可以遍历Object.keys(跳过前三个),但请记住——严格来说,JS 对象是无序的。
    • 您可以在循环for ( ...; i &lt; l &amp;&amp; allButFirstThreeAreNull; ...)中添加条件来删除break语句。
    • 啊,对不起,忽略前面的评论;以为您已经讨论过将其添加到内部条件中。是的,它可能会被这样重写,但我实际上在这里的break 中没有发现任何问题。
    【解决方案3】:

    您可以将Object.keys()Array.prototype.every() 一起使用。

    演示: http://jsfiddle.net/akstE/1/

    var result = Object.keys(myObject)
        .every(function(key) {
            switch (key) {
                // Change these to your actual property names
                case "a1": case "a2": case "a3":
                    return true; // assuming you don't need to check them at all
                default:
                    return myObject[key] === null; // `== null` to include `undefined`
            }
        });
    

    (在旧版浏览器中这两种方法都需要 shims。)

    【讨论】:

    • 为什么这个循环会在 switch 发现 false 时停止?但如果是真的继续?尝试添加 console.log(key) 看看我的意思
    • @DonnyP:是的,一旦出现故障,它就会短路结束。
    • 所以当我们“返回真”时会发生“短路”?如果它返回 false,然后继续另一个“每个”循环?
    • @DonnyP:不,.every() 检查是否所有项目都通过了给定的任何条件。一旦我们return false; 知道并非所有项目都满足条件,它就会停止。如果所有项目都满足给定条件,它将一直持续到最后,并且永远不会收到false 结果。
    • 不,这意味着return falseevery 的本质是返回 false 并在找到第一个不合格元素后停止迭代。检查the doc
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 2014-08-22
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多