在Javascript中,<int-value> == "<int-value>"被评估为true。为什么会这样?

11
如果我执行0 == "0",它会评估为true。请尝试,
if( -777 == "-777" ) alert("same");

弹出警告。

另外,需要注意的是 true == "true" 并不会被计算为 true。试一下:

if( false == "false" ) alert("same");

为什么弹出警告框(alert)没有发生?


这是一个重复的问题,链接为https://dev59.com/Z3RC5IYBdhLWcg3wROpQ - Paolo Bergantino
Paolo,我认为我的问题有点不同。另一个问题是“== vs ===”。而在我的问题中,还涉及到bool == "<bool>",而另一个问题并没有涉及到这一点。但是,这两个问题是相关的。 - Real Red.
1
问题的措辞可能不同,但概念在两者中是相同的。 - Paolo Bergantino
是的,同意,但第二部分不同! - Real Red.
我认为这个问题与“== vs. ===”的问题不同。安德烈的答案很有启发性。 - David Kolar
8个回答

33

== 的行为有点冗长,但在 ecma-262规范 中已经明确定义:

11.9.3 抽象等同比较算法
比较 x == y,其中 x 和 y 是值,产生 true 或 false。此类比较的执行方式如下:
1. 如果 Type(x) 与 Type(y) 不同,则转到步骤 14。 2. 如果 Type(x) 是 Undefined,则返回 true。 3. 如果 Type(x) 是 Null,则返回 true。 4. 如果 Type(x) 不是 Number,则转到步骤 11。 5. 如果 x 是 NaN,则返回 false。 6. 如果 y 是 NaN,则返回 false。 7. 如果 x 是与 y 相同的数字,则返回 true。 8. 如果 x 是 +0,y 是 -0,则返回 true。 9. 如果 x 是-0,y 是 +0,则返回 true。 10. 返回 false。 11. 如果 Type(x) 是 String,则仅当 x 和 y 完全相同(长度相同且相应位置上的字符相同)时返回 true。否则,返回 false。 12. 如果 Type(x) 是 Boolean,则仅当 x 和 y 都为 true 或 false 时返回 true。否则,返回 false。 13. 如果 x 和 y 引用相同的对象或引用互相连接的对象 (参见 13.1.2),则返回 true。否则,返回 false。 14. 如果 x 为 null 且 y 为 undefined,则返回 true。 15. 如果 x 为 undefined 且 y 为 null,则返回 true。 16. 如果 Type(x) 为 Number 而 Type(y) 为 String,则返回比较结果 x == ToNumber(y)。 17. 如果 Type(x) 为 String 而 Type(y) 为 Number,则返回比较结果 ToNumber(x) == y。 18. 如果 Type(x) 为 Boolean,则返回比较结果 ToNumber(x) == y。 19. 如果 Type(y) 为 Boolean,则返回比较结果 x == ToNumber(y)。 20. 如果 Type(x) 是 String 或 Number 而 Type(y) 是 Object,则返回比较结果 x == ToPrimitive(y)。 21. 如果 Type(x) 是 Object 而 Type(y) 是 String 或 Number,则返回比较结果 ToPrimitive(x) == y。 22. 返回 false。
第16步适用于您先前的示例:
   0 == "0"            // apply 16
≡  0 == toNumber("0")
≡  0 == 0              // apply 7
≡  true

第18步,然后将第16步应用于后者:

   true == "true"            // apply 18
≡  toNumber(true) == "true"
≡  1 == "true"               // apply 16
≡  1 == toNumber("true")
≡  1 == NaN                  // apply 6
≡  false

7
为了优秀的回答加上0.8分,为找到≡字符加上0.2分。 - nickf
非常好,你回答了两个问题都很好。 - Real Red.
2
你一定会喜欢这个规范的作者如何使用goto来高效地生成意大利面条式代码,而不需要编码! - configurator

11

做这个:

if(5 == "5")

让 JavaScript 将第一个数字 5 转换为字符串。尝试这个:

if(5 === "5")

=== 运算符会使 JavaScript 同时比较类型和值。

这实际上是这个 问题 的重复,那里已经解释得非常清楚了。


7

由于JavaScript是一种弱类型语言,它会根据操作和其他变量的类型来静默转换你的变量。

alert ("5" - 1);  // 4  (int)
alert ("5" + 1);  // "51" (string) "+" is a string operator, too
alert ("5" == 5); // true

你可能需要关注的是身份检查 (===)。这将确保变量是 完全相同,而不仅仅是相等

alert("5" == 5);  // true, these are equal
alert("5" === 5); // false, these are not identical.

还可以参考这个问题:如何区分相等和恒等比较运算符? PHP的实现与JavaScript非常相似。


4

JavaScript有两组相等运算符:

  • ===和!==(严格相等运算符)
  • ==和!=(标准相等运算符)

如果操作数是相同类型的,标准相等运算符将执行正确的比较,但如果它们不是相同的类型,您可能会得到一些意外的结果,例如:

'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
' \t\r\n ' == 0 // true

因此我建议始终使用严格相等运算符(===,!==)。


1

Javascript不会将“false”转换为布尔值false,只会转换为字符串“false”。

您可以宽松地将字符串值转换为它们的整数等价物,因此您的第一个示例可以正常工作。


JavaScript将“false”转换为“false”? - Iraimbilanja
bool(false) 等于 str("0"),bool(true) 等于 str("1")。 - nickf
对,我的意思是它分别转换为0和1表示false和true。 - Chris Ballance

1
JavaScript是一种弱类型语言,因此在解释器认为需要时,会在运行时进行类型转换。如果您将整数与字符串进行比较,则它们应该是相同的类型,因此例如"34" == 34 是true,因为在比较之前整数可能会被强制转换为字符串。
字符串"false"不会转换为bool,相反,bool false会转换为一个字符串,这个字符串实际上包含数字0,即"0",所以"0" == "false"是明显错误的。
如果要比较值而不进行自动类型转换,有效地比较类型和值,请使用三等号:
5 === "5" false "string" === "string" true

1
为什么会这样呢?
因为JavaScript既是松散类型的,又是极不一致的。它的设计特性并非都经过深思熟虑;相比其他编程语言,它的创建、实现和部署速度非常快,只是为了赶在Netscape 2.0发布之前完成。直到很久以后,它才稳定下来,消除了一些最严重的错误,并变得半标准化。
试图寻找隐式类型转换规则等事物的哲学原理可能是徒劳无功的。JavaScript唯一真正遵循的一项原则是DWIM,但这种原则往往是负面的。

0
JavaScript 定义了 0、布尔值 false 和未定义的值为假值。任何字符串如果不是 "0",即使该字符串是 'false',也将被视为真值。
这有点烦人,真的。

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