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”算法,大致 归结为这些步骤。可以发生连续的强制转换。
- 如果一个操作数是原语而另一个是对象(包括数组),则 not so simple algorithm 用于将对象强制转换为原语,这可能涉及(除其他事项外)对象的
toString
、valueOf
或 [Symbol.toPrimitive]
方法。
- 布尔值被强制转换为数字。
- 如果一个操作数是数字,另一个是字符串,则字符串被强制转换为数字。
null
和 undefined
被认为等于他们自己和彼此,没有别的。否则执行 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
.否则我坚持使用 ===
,这更容易推理。
学习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”算法,大致 归结为这些步骤。可以发生连续的强制转换。
- 如果一个操作数是原语而另一个是对象(包括数组),则 not so simple algorithm 用于将对象强制转换为原语,这可能涉及(除其他事项外)对象的
toString
、valueOf
或[Symbol.toPrimitive]
方法。 - 布尔值被强制转换为数字。
- 如果一个操作数是数字,另一个是字符串,则字符串被强制转换为数字。
null
和undefined
被认为等于他们自己和彼此,没有别的。否则执行 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
.否则我坚持使用 ===
,这更容易推理。