【问题标题】:Javascript: testing for at least one non-empty array (if one of the arrays may be null)Javascript:测试至少一个非空数组(如果其中一个数组可能为空)
【发布时间】:2017-07-27 11:34:14
【问题描述】:

给定两个数组 myArray1 和 myArray2,可能是 null,我如何输出一个布尔值来告诉我至少一个数组是否非空?

假设我有以下变量:

    myArray1 = ["one", "two", "three"]; //-> non-empty array
    myArray2 = null; //-> not an array (in my case this happens from .match() returning no results)

我想要一个表达式,这样myArray1 && myArray2 将为 FALSE,但 myArray1 || myArray2 将为 TRUE。

我确实查看了其他相关的 Stack Overflow 问题(请参阅下面的精简列表),但由于我仍在努力找出解决方案,我想我会将其作为一个单独的问题发布,因为答案也可能对其他人有益。

空数组的常用测试方法是:

    myBooleanOr = (myArray1.length || myArray2.length); //3
    myBooleanAnd = (myArray1.length && myArray2.length); //Error

这在两个变量都是数组的情况下有效,但在这种情况下,第二个变量会抛出错误:无法读取'null'的属性长度。使用Boolean() 函数并不能解决问题,因为以下也会引发同样的错误:

    myBooleanAnd = (Boolean(myArray1.length) && Boolean(myArray2.length)); //error

在几个 Stack Overflow 问题中接受的测试空数组的解决方案是使用 typeof myArray !== "undefined",但这仍然不能解决问题,因为两个数组都不匹配 "undefined",所以 myBooleanAnd 仍然会抛出一个错误:

   var bool = (typeof myArray1 !== "undefined"); //true
   var bool = (typeof myArray2 !== "undefined"); //true
   var myBooleanAnd = ((typeof myArray1 !== "undefined" && myArray1.length) || (typeof myArray2 !== "undefined" && myArray2.length)); //Error: cannot read property length of null

将数组与 [] 进行比较,这似乎也很直观,但也不起作用,因为两个数组都不匹配 []

    var bool = (myArray1 !== []); //true
    var bool = (myArray2 !== []); //true

其他相关帖子

有关 Stack Overflow 的其他一些问题涉及空 Javascript 数组的测试,包括:

还有关于Javascript中空数组真值的问题:

更新

我已更正原始问题中发布的以下错误(感谢指出错误的人)。我在这里列出它们,因为它们也可能对其他人有帮助:

  • ==!改为!==
  • typeof x === undefined,改为typeof x === "undefined"

【问题讨论】:

  • JavaScript 中没有 ==! 运算符。你要找的接线员是!==
  • @JLRishe hm 我想知道这一点,但我已经对它们进行了测试,它们都可以工作......这是“最佳实践”的问题还是只是一个约定?
  • 不,两者都不是。 ==!== ! 的间隔很差的等价物,即 1 == !'a'1 == falsefalse。我想如果您在任何地方都使用==!,那么您的很多代码的行为都会与您的预期不同。

标签: javascript arrays null


【解决方案1】:

我建议使用辅助函数来确定单个数组是否为非空,然后使用两次。这简单明了:

function isNonEmptyArray(arr) {
    return !!(Array.isArray(arr) && arr.length);
}

var myBooleanAnd = isNonEmptyArray(myArray1) && isNonEmptyArray(myArray2);
var myBooleanOr = isNonEmptyArray(myArray1) || isNonEmptyArray(myArray2);

【讨论】:

  • !! 是拼写错误,还是与! 有不同的含义? (return关键字后的括号前)
  • !! 将“真实”或“虚假”值强制转换为 truefalse。例如!!"hello"true。这不是错字。
  • 那么是否相当于Boolean()函数呢?
  • @ATJ 是的。
【解决方案2】:

好的,那么,代码示例中有一堆错误,我会尽力解释它们:

myBooleanOr = (myArray1.length || myArray2.length); //3
myBooleanAnd = (myArray1.length && myArray2.length); //错误

在这里,第一行返回它遇到的第一个真值。由于myArray1 有一个length > 0,它返回该值并且从不评估条件的第二部分,这就是您没有收到错误的原因。交换支票,它就会坏掉。
第二行将两个值结合起来给出一个结果,所以当两个变量之一是null时总是会报错。

var bool = (typeof myArray1 === undefined); //假

typeof 返回一个字符串,如果将其与 undefined 常量进行比较,则它始终为 false,正确的语句是 typeof myArray1 === "undefined",正如您链接的大多数帖子中所写的那样

var bool = (myArray2 ==!null);

“严格不等于”运算符是!== 而不是==!。您正在执行不同的操作,这就是为什么您会得到令人惊讶的结果。

在语法中添加正确的空格,这是您的代码var bool = (myArray2 == !null);

所以你布尔翻转 null 的值,这本质上是假的,变成真的,然后比较 myArray2 是否松散地等于 true ... 因为 myArray2null ,正如我们所说的那样是虚假的,比较会返回false


也就是说,对于这个问题的解决方案,我会提出一个稍微长一点的语法,它更明确、更易于理解,并且您可以扩展以检查您喜欢多少个数组而不会增加更多复杂性:

var myArray1 = [1,2,3]
var myArray2 = null

var arrays = [myArray1, myArray2]

var oneNotEmpty = arrays.some( a => typeof a != "undefined" && a != null && a.length > 0)

console.log("At least one array non-empty?", oneNotEmpty)

【讨论】:

    【解决方案3】:

    您可以使用isArray 来检查某个东西是否为数组。大多数现代浏览器都支持它。 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

    然后你可以结合isArray 和数组的长度来检查某个东西是否是一个有效的非空数组。

    function isOneNotEmpty(arrayOne, arrayTwo){
    	
    	return (Array.isArray(arrayOne)? arrayOne.length > 0 : false) || (Array.isArray(arrayTwo)? arrayOne.length > 0 : false)
    }
    
    console.log(isOneNotEmpty([],null));
    console.log(isOneNotEmpty([1,2,3,4],null));
    console.log(isOneNotEmpty([3,4,5],[1]));

    【讨论】:

      【解决方案4】:

      对数组的测试很简单:

          var blnIsPopulatedArray = (myArray != null
                                  && typeof myArray == "object" 
                                  && typeof myArray.length == "number"
                                  && myArray.length > 0);
      

      如果 'myArray' 不是包含至少一项的数组,则返回 false,如果是包含至少一项的数组,则返回 true。

      【讨论】:

      • (typeof null == "object") 返回 true,因此针对“object”的测试不会排除 myArray2。然后 myArray2.length 的测试类型将返回 Error: cannot read property length of null...
      • @ATJ,这就是为什么我也在测试长度,如果 myArray 为空,长度将无效。
      【解决方案5】:

      一种解决方案如下(有或没有Boolean()):

      使用 Array.isArray() 和 array.length:

         var myBooleanAnd = Boolean(Array.isArray(myArray2) && myArray2.length) && Boolean(Array.isArray(myArray1) && myArray1.length) ; //false -> OK
         var myBooleanOr = Boolean(Array.isArray(myArray2) && myArray2.length) || Boolean(Array.isArray(myArray1) && myArray1.length) ; //true -> OK
      

      也可以使用myArray1 !== null 代替Array.isArray(myArray1),但由于后者是更具体的测试,更广泛的 Array.isArray() 方法似乎更可取。

      更新

      我之前曾建议使用以下内容:

          var myBooleanAnd = Boolean(myArray1 && myArray2); //returns false -> OK
          var myBooleanOr = Boolean(myArray1 || myArray2); //returns true -> OK
      

      但是,正如@JLRishe 所指出的,以下表达式也返回 TRUE,这不是一个安全的解决方案,因为它只适用于数组永远不会为空的情况。

         var bool = Boolean([] && []); //returns true -> false positive
      

      【讨论】:

      • #1 没有达到既定目标。它不检查它们是数组还是非空。
      • @JLRishe 该问题询问如果至少有一个数组包含值,如何获得 TRUE。 #1 确实这样做了……我错过了你的意思吗?
      • 如果它们是两个空数组,它也会产生 true。这将是一个误报,意味着它不能达到其所需的目的。
      【解决方案6】:
      function arrayIsEmpty(array) {
       if (!Array.isArray(array)) {
         return false;
       }
       if (array.length == 0) {
         return true;
       }
      }
      

      【讨论】:

        猜你喜欢
        • 2014-06-15
        • 2019-12-09
        • 1970-01-01
        • 1970-01-01
        • 2014-09-24
        • 2019-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多