为什么 ('0' ? 'a' : 'b') 的行为与 ('0' == true ? 'a' : 'b') 不同?

111
为什么以下两个语句的结果不同?
('0' ? 'a' : 'b') /* -> 'a' */
('0' == true ? 'a' : 'b') /* -> 'b' */

jsFiddle测试用例

编辑:

我应该补充说明,我怀疑第一个语句中的'0'被强制转换为布尔值进行比较,这应该与"'0' == true"完全相同。很明显这不是正确的。


我认为 ('0' == false) 也是false。 - Iarek
1
第二个语句中的字符串似乎被转换为布尔值。('1' == true)- > true,('0' == false)- > true。 - Strayer
6个回答

207

首先,为了完整性:

('0' ? 'a' : 'b') 

因为'0'非空字符串,总是评估为true,所以'a'true

字符串:如果参数是空字符串(长度为零),则结果为false;否则结果为true


现在看'0' == true

这里会进行两次类型转换。我们可以在规范的第11.9.3节“抽象相等比较算法”中了解这一点。

操作数表示为xy (x == y)。

在我们的情况下,x是一个字符串('0'),而y是一个布尔值(true)。因此执行步骤7:

如果Type(y)是Boolean,则返回比较x == ToNumber(y)的结果。

当布尔值转换为数字时,会进行以下转换

布尔值:如果参数是true,则结果为1。如果参数是false,则结果为+0

现在我们有:

'0' == 1

符合第5步条件的内容为:

如果x的类型是字符串,且y的类型是数字,则返回比较ToNumber(x) == y的结果。

字符串如何转换为数字更加复杂,但当然也可以在规范中找到。

因此最终的比较为:

0 == 1

这是 false (步骤1.a.vi.)


8
('0' ? 'a' : 'b'); /* -> 'a' */

0是一个字符串值,每个非空字符串被评估为true,并且不作为布尔值测试。如果删除引号:

(0 ? 'a' : 'b'); /* -> 'b' */

现在你将收到 b - 0 不是一个字符串,会被视为 false!

('0' == true ? 'a' : 'b'); /* -> 'b' */

0被视为bool类型 两者被视为数字,即false。从specs中可以看到,11.9.3抽象相等比较算法指出可能需要执行多个转换才能比较同一类型的变量。


实际上,你所说的“0”被评估为布尔值是不正确的,实际发生的是_true_被评估为数字,这迫使“0”被评估为数字。这是你指向的规范的直接结果。请参见Felix King的答案。 - Paul Wagland

3
因为'0'不等于1,所以它不等于true,尽管它也不是false。 在第一种情况下,当'0'被强制转换为bool时,类型转换运算符会将除0之外的所有内容都返回true。

1
主要是因为JavaScript在真实性方面相当不一致。但答案是:
  1. 在这种情况下,'0'被直接转换为Boolean值,而'0'作为一个非空字符串是true。
  2. 在这种情况下,不会进行转换;字符串不等于布尔值。

4
好的,('1' == true)是真的;)第二个语句中没有===。 - Strayer
1
我认为它相当一致,问题在于我们如何尝试使用它。有些东西并不是像我们想象的那样去使用的。但这一切都是解释的问题,这导致了不同的解决方案等等,并不像数学中的某些普遍真理那样。 :) - Bakudan
8
你的第二点是错误的。转换确实发生了。 - Felix Kling

-3
那是因为'0'在if语句中被视为真,但不被认为等于true。就像3和17都是真的,但不相等。

-4

('0' ? 'a' : 'b') --> 0代表假,而'0'是一个字符串,因此不是假 在这种情况下,0、null或''(空字符串)被视为假

('0' == true ? 'a' : 'b') --> 如其他人所述,将某个字符串与布尔值TRUE进行比较并不等于TRUE


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