为什么空 JavaScript 数组在条件结构中的计算结果为 true?

我在代码中遇到了很多 bug,因为我期待这样的表达:

评估 Boolean([]);为假。

但事实并非如此,因为它被评估为真。

因此,可能返回如下 []的函数:

// Where myCollection possibly returned [ obj1, obj2, obj3] or []
if(myCollection)
{
// ...


}else
{
// ...
}

没有做预期的事情。

我假设 []是一个空数组是错误的吗?

此外,这种行为在所有浏览器中都是一致的吗?还是也有陷阱?顺便说一句,我在谷歌浏览器中观察到了这种行为。

125747 次浏览

您应该检查该数组的 .length,看看它是否包含任何元素。

if (myCollection) // always true
if (myCollection.length) // always true when array has elements
if (myCollection.length === 0) // same as is_empty(myCollection)

来自 http://www.sitepoint.com/javascript-truthy-falsy/

下列数值总是错误的:

  • 假的
  • 0(0)
  • 0n (BigInt 零)
  • “”(空字符串)
  • 无效
  • 未定义
  • NaN (一个特殊的 Number 值,意味着 Not-a-Number!)

所有其他值都是 true,包括 "0"(引号中为零)、 "false"(引号中为 false)、空函数、空数组([])和空对象({})。

关于 为什么,我怀疑这是因为 JavaScript 数组只是一种特殊类型的对象。特别处理数组将需要额外的开销来测试 Array.isArray()。此外,如果在这个上下文中,真数组的行为与其他类似数组的对象不同,而让所有类似数组的对象的行为相同,这可能会让人感到困惑,而让所有类似数组的对象的行为相同则会更加昂贵。

[]等于 false时,它的计算结果为 true

是的,这听起来很糟糕,或者至少有点令人困惑。看看这个:

const arr = [];
if (arr) console.log("[] is truethy");
if (arr == false) console.log("however, [] == false");

实际上,如果您想检查某个内容是否为空, 然后检查 length。(?.操作员确保 null也被覆盖。)

const arr = []; // or null;
if (!arr?.length) console.log("empty or null")

还要补充的是,JavaScript 中的所有对象(数组也是对象)都作为链接存储在内存中,这些链接总是不为空或零,这就是为什么 Boolean({}) === trueBoolean([]) === true

这也是为什么相同的对象(通过值而不是链接复制)总是不相等的原因。

{} == {} // false


let a = {};
let b = a; // copying by link
b == a // true

和 JavaScript 一样,所有东西都是一个对象,因此对于 false 和 null,我使用以下条件:

if(value && Object.keys(value).length){
// Not falsy and not empty
}
else{
// falsy or empty array/object
}

我怀疑它与离散数学和条件(如果是的话)的工作方式有关。一个条件有两部分,但是在第一部分不存在的实例中,不管第二部分是什么,它都会返回一个叫做空真的东西。

下面是维基百科中关于空洞真相的例子

如果房间里没有手机,那么“房间里所有手机都关机”的声明就是真的。在这种情况下,“房间里所有的手机都打开了”的说法也是空洞的真实

维基百科甚至稍后还特别提到了 JavaScript。

Https://en.wikipedia.org/wiki/vacuous_truth#:~:text=in%20mathematics%20and%20logic%2c%20a,the%20antecedent%20cannot%20be%20satisfied.&text=one%20example%20of%20such%20a,eiffel%20tower%20is%20in%20bolivia%22.

[]==false  // returns true

由于在 ECMA 规范 # 第11.9.3节中提到的抽象等式算法,这个结果的计算结果为 true

如果您运行上面提到的算法。

第一次迭代中,满足的条件是,

Step 7: If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).

因此,上述条件转换为-> [] == 0

现在在 第二次迭代中,[] == 0满足的条件是:

Step 9: If Type(x) is Object and Type(y) is either String or Number, return the result of the comparison ToPrimitive(x) == y.

[]是一个对象,因此,在转换为原语时,它转换为一个空字符串 ''

因此,上述条件转换为-> '' == 0

第三次迭代中,满足的条件是:

Step 5: If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.

我们知道,空字符串 ''falsy值,因此将空字符串转换为数字将返回值 0

今后,我们的条件,将转变为-> 0 == 0

第四次迭代中,满足第一个条件,其中类型相等,数字相等。

从此,[] == false的最终值减少到 0 == 0,这是真的。

希望这个回答了你的问题。否则,你也可以参考这个 Youtube 视频