JavaScript 传递相等

JavaScript transitive equality

学习JavaScript,发现给定下面的表达式,当给定这个表达式时,它的计算结果为真:transitive([1], 1, {toString:_=>'1'});

我不明白为什么。

y和z相等是有道理的,但是x和z不相等怎么能相等呢?

function transitive(x,y,z) {
     return x && x == y && y == z && x != z;
}

在JavaScript中有"truthiness"和"falsyness"的概念。 1'1' 等值与 == 等松散比较运算符相比是相等的,但使用 === 等严格相等运算符时并不严格相等。

该对象等于 1,因为 JavaScript 使用类型强制将对象转换为与基本类型相当的值。它通过调用对象的 .toString() 方法来做到这一点,其中 returns '1' 和我们在上面了解到的一样是真实的, 1 也是如此,因此在使用时它们被认为是相等的==.

这可能是相关的:MDN: Equality comparisons and sameness

best/common JavaScript 的做法是始终使用 ===!== 代替 ==!=

“松散”equality operator in javascript (==) is not transitive. This is primarily a result of type coercion that occurs before comparison. == uses javascript's "abstract equality”算法,大致 归结为这些步骤。可以发生连续的强制转换。

  1. 如果一个操作数是原语而另一个是对象(包括数组),则 not so simple algorithm 用于将对象强制转换为原语,这可能涉及(除其他事项外)对象的 toStringvalueOf[Symbol.toPrimitive] 方法。
  2. 布尔值被强制转换为数字。
  3. 如果一个操作数是数字,另一个是字符串,则字符串被强制转换为数字。
  4. nullundefined 被认为等于他们自己和彼此,没有别的。否则执行 strict equality comparison

单个运算符包含了很多复杂性,结果是一个非常摇摆不定的相等性概念和一堆陷阱。

// Is an empty array truthy or falsey?
[] == false;       // -> true, so [] is falsey?
[] ? true : false; // -> true, so [] is truthy?

// Another case of intransitivity:
false == "0"  // -> true
false == []   // -> true
"0" == []     // -> false

// Not super consistent
123 == "123"       // -> true
123 == [123]       // -> true
true == "true"     // -> false
true == [true]     // -> false
"true" == [true]   // -> true
true == ["1"]      // -> true

将这些强制转换规则应用于您的示例:

[1] == 1 
// Object is coerced to primitive, in this case via toString
"1" == 1
// String is coerced to number
1 == 1
/* true */
1 == {toString:_=>'1'}
// Object is coerced to primitive, in this case via toString
1 == "1"
// String is coerced to number
1 == 1
/* true */
[1] == {toString:_=>'1'}
// Since neither value is a primitive, no coercion occurs. 
// Reference equality is checked instead.
/* false */

我使用 == 的唯一原因是通过一次比较检查一个值是否是 null undefined .否则我坚持使用 ===,这更容易推理。