为什么 "[] == true" 和 "![] == true" 都会被判断为假?

6

我有两个像这样的语句。为什么它们都会评估为 false

console.log([] == true)
console.log(![] == true)

如果[] == truefalse,那么![] == true不应该得到true吗?

6
不,如果[] == truefalse,那么[] != true就是true。否定两边没有相同的语义。考虑一下3 == 2false,对吧?那么为什么!3 == 2会是true呢? - VLAZ
5个回答

9
这是强制类型转换的方式。
强制类型转换的第一步是将任何非原始类型转换为原始类型,然后使用一组规则将左侧、右侧或两侧都转换为相同的类型。你可以在这里找到这些规则。
在你的例子中,[] == true会经过以下4个步骤:
  1. [] == true
  2. [] == 1
  3. "" == 1
  4. 0 == 1
而根据运算符优先级![] == true中的!首先被执行,因此表达式转换为false == true,显然是false

您可以尝试实时演示,由Felix Kling提供,以更好地了解sameness运算符的工作原理。

更详细地说:

![]false,因为[]是一个对象(数组是对象),所有对象,不包括null,都是truthy。 因此,任何数组,即使它为空,也始终是truthy,而truthy的相反是false。 检查值是否为truthy的最简单方法是使用!!

console.log("![]: " + ![]);
console.log("!![]: " + !![]);

当您使用宽松比较(使用 == 而不是 === )时,您要求JavaScript引擎首先将值转换为相同的类型,然后再进行比较。所以发生的是根据一组规则转换值,一旦它们是相同的类型,它们就会通过与严格等式检查( === )相同的过程进行比较。 [] 经历的第一个变化是被转换为字符串,空数组的字符串版本是空字符串“”,然后将空字符串转换为数字,空字符串的数值为 0 ,由于 true 的数值为 1 ,而 0 != 1 ,最终输出为 false 。

console.log("[] == true => `" + ([] == true) + "`");

console.log("String([]) => `" + String([]) + "`");
console.log("Number('') => `" + Number("") + "`");

console.log("Number(true) => `" + Number(true) + "`");


我不确定我理解这个问题,你能详细说明一下为什么 ![] 的值为 false,如果 [] 的值也是 false 吗? - Sepehr Nazari
@SepehrNazari 我已经在答案中添加了更多细节。 - nick zoum

2
根据“抽象相等比较算法” - http://es5.github.io/#x11.9.3
当检查x==y时,会检查x和y的类型。如果没有匹配的规则,则返回false。
以下是两个例子:
  1. 对于[] == true,匹配规则7,因此返回[] == ToNumber(true),即返回false
  2. 你得到![] == true的相同结果的原因是![]返回false,而false == true返回false
为了获得第二个操作的相反结果,请使用括号将表达式包起来。
console.log(!([] == true)); // returns true

1

在控制台中输入![]。它是false

因此,![] == truefalse == true相同,即false

[] != truetrue


我认为它没有回答问题。问题本质上是如果[]false,那么为什么![]也是false。在数学和逻辑中,false的否定是true。因此,这是一个有效的问题。答案比较复杂。 - ba_ul
这并不复杂。[] 不是 false。你应该了解数据类型、强制转换、类型转换、相等性、身份、=====[] == false -> true 但是 [] === false -> false。这不是数学,而是编程,根据相等运算符和上下文,有多种方式来理解某个东西的“是什么”。 - pixelearth
让我再试一次。
  1. 我没有说 [] 就是 false。我是在解释这个问题:如果 [] == true 产生的结果是 false,那么就意味着 []false。在 JavaScript 规范中,空数组是真实值。问题是这背后的矛盾在哪里。请参见 Nick Zoum 和我的答案,它们解释了原因。
  2. 你的回答以 ! []false 开头。这避开了 [] == true 为什么是假的问题。所以它没有回答问题。
  3. 查阅离散数学和命题逻辑。它们是编程的基础。
- ba_ul
你提到:[] == false -> true[] === false -> false 当然。但这与问题有什么关系呢? - ba_ul

1

迄今为止,所有的答案都没有解决主要问题。[编辑:这已经不再是真的了,请参见Nick Zoum的答案。]

本质上,问题是这样的:

[] == true 返回 false
=> [] 不是 true
=> []false(因为不是真的就是假的)
=> ![] 应该是 true,因为对 false 取反是 true。那么为什么 ![] == true 返回 false


[]实际上是真值。因此,![]实际上为假值。
然而,[] == true返回false——原因是强制类型转换。这是JavaScript的又一个坑点。
当一个数组被显式地与布尔值(即truefalse)进行相等性比较时,它的元素首先被转换为字符串,然后连接在一起。因此,一个空数组变成了""——问题就在这里,因为空字符串是假值。
简而言之,一个空数组是真值,但它在与布尔值进行比较时被强制转换为一个空字符串,这是假值。
请注意以下内容,它来自于https://www.nfriedly.com/techblog/2009/07/advanced-javascript-operators-and-truthy-falsy/

数组特别奇怪。如果你只测试它的真实性,一个空数组是真的。然而,如果你将一个空数组与布尔值进行比较,它变为假:

if ( [] == false ) {
     // this code runs }

if ( [] ) {
    // this code also runs }

if ([] == true) {
    // this code doesn't run }

if ( ![] ) {
  // this code also doesn't run } 

(这是因为当你进行比较时,它的元素会被转换为字符串并连接起来。由于它是空的,因此变成了“”,然后就是假值。是的,这很奇怪。)

0

阅读https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

JavaScript中等于运算符(==)的规则

如果


type(x)            type(y)                    result

1.x and y are the same type    See Strict Equality (===) Algorithm

2.null              Undefined                 true

3.Undefined           null                    true

4. Number            String                 x == toNumber(y)

5. String            Number                  toNumber(x) == y

6. Boolean           (any)                  toNumber(x) == y

7. (any)              Boolean               x == toNumber(y)

8.String or Number    Object                x == toPrimitive(y)

9.Object            String or Number          toPrimitive(x) == y

***10.otherwise…                                 false


你是从规格推导出那个表格的吗?加上数据来源可能会更好。 - str
这个回答并不是很有用。您没有解释这个表格如何解决正在讨论的问题。 - ba_ul

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接