在JavaScript中,为什么“ 0”等于false,但是在通过“ if”进行测试时,其本身不是false?


232

下面显示"0"了Javascript中的false:

>>> "0" == false
true

>>> false == "0"
true

那么,为什么要打印以下内容"ha"

>>> if ("0") console.log("ha")
ha

47
"0"是一个字符串,并且由于它不是空的,因此被评估为true。
Digital Plane's

8
"0" === false [...] false

3
在javascript中查看Angus Croll的文章真相。javascriptweblog.wordpress.com/2011/02/07/...
timrwood

8
'0'==false但「0」不是假值(是的Java语言可能很怪异)
Linsey 2011年

5
@Linsey:整个“虚假的”和“真实的”只是用来解释如何将值转换为布尔值。当您使用比较两个值时==,它们永远不会转换为布尔值,因此不适用。(转换规则似乎倾向于转换为数字。)
millimoose 2011年

Answers:


251

原因是因为当您显式这样做时"0" == false,双方都将转换为数字,然后执行比较。

当您执行以下操作:时if ("0") console.log("ha"),正在测试字符串值。任何非空字符串为true,而空字符串为false

等于(==)

如果两个操作数的类型不同,则JavaScript会转换操作数,然后进行严格比较。如果操作数是数字或布尔值,则如果可能,将操作数转换为数字;否则,操作数将转换为数字。否则,如果其中一个操作数是一个字符串,则将另一个操作数转换为字符串(如果可能)。如果两个操作数都是对象,则JavaScript将比较内部引用,当操作数引用内存中的同一对象时,内部引用是相等的。

(从 比较运算符在Mozilla开发者网络)


348

显示问题的表格:

如果声明为真

和== javascript中所有对象类型的真实比较

故事的寓意=== 严格平等显示理智

表生成功劳:https : //github.com/dorey/JavaScript-Equality-Table



3
从现在开始,如果有人说他从不使用严格的比较运算符,那么我将面对这些表并让他哭泣。仍然不确定我是否掌握了NaN虽然。我的意思是,typeof NaN // number但是NaN === NaN // false,嗯...
Justus Romijn 2014年

4
我的一个朋友制作了f.cl.ly/items/3b0q1n0o1m142P1P340P/javascript_equality.html-与上面的图表相同,但更易于阅读。
露西·贝恩

@JustusRomijn有多个值可以表示NaN,因此当您比较两个NaN时,它们具有不同的值(我想)。在这里阅读第一句话。
cychoi,2015年

4
这些表有一个错误。无论是==还是===运营商的[]{}[[]][0][1]值不计算为true。我的意思是[] == [][] === []也是假的。
Herbertusz

38

根据规范。

12.5 if语句 
.....

2.如果ToBoolean(GetValue(exprRef))为true,则 
一个。返回评估第一条陈述的结果。
3.其他 
....

根据规范,ToBoolean是

根据表11,抽象操作ToBoolean将其参数转换为Boolean类型的值:

该表说明了有关字符串的信息:

在此处输入图片说明

如果参数为空String(长度为零),则结果为false;否则,结果为false。否则结果为真

现在,解释一下为什么"0" == false您应该阅读均等运算符,该运算符声明其从抽象操作获取的值GetValue(lref)与右侧的相同。

将该相关部分描述为:

如果是IsPropertyReference(V),则 
一个。如果HasPrimitiveBase(V)为false,则让get为base的[[Get]]内部方法,否则让get
是下面定义的特殊[[Get]]内部方法。 
b。返回使用base作为此值调用get内部方法并传递的结果
参数的GetReferencedName(V)

换句话说,字符串具有原始基数,该基数会回调内部的get方法并最终看起来为false。

如果要使用GetValue操作use评估事物==,如果要使用ToBoolean,use ===(也称为“严格”相等运算符)来评估事物


"a string has a primitive base, which calls back the internal get method and ends up looking false"所有的字符串都是这样吗?
aziz punjani 2011年

@Interstellar_Coder Section 8.12.3: [[Get]] (P)描述了它的工作方式。仅在字符串为0的情况下才是正确的,因为这样做会进行一系列其他内部调用,最终导致GetOwnProperty“ whatever”是数据属性,然后返回该值。这就是为什么“ 0”为假,而“ blah”为真的原因。查阅Douglas Crockford在Yahoo开发人员剧院上的一些视频,他描述了JavaScript中的“真实性”,比我复杂得多。如果您理解“真实”和“虚假”的含义,您将立即理解波宾斯的回答。
隐身

1
在哪里可以找到规格?
user985366

12

在PHP中,字符串"0"是虚假的(在布尔上下文中使用时为false)。在JavaScript中,所有非空字符串都是真实的。

诀窍在于,==针对布尔值的运算符不会在布尔值上下文中求值,它会转换为数字,并且如果是通过将字符串解析为十进制来完成的话。因此,您将获得Number 0而不是true布尔值true

这在语言设计上确实很差劲,这也是我们尝试不使用不幸的==运算符的原因之一。使用===代替。


7
// I usually do this:

x = "0" ;

if (!!+x) console.log('I am true');
else      console.log('I am false');

// Essentially converting string to integer and then boolean.

4

您在引号周围将0其设置为字符串,该字符串被评估为true。

删除引号,它应该工作。

if (0) console.log("ha") 

是正确的,而不是关于如何使其“正常运行”,而是问题更像是“为什么这样运行?”
极性2014年


1

“ if”表达式测试真实性,而双等于测试类型独立性等效。正如这里其他人指出的那样,字符串始终是真实的。如果双等式正在测试两个操作数的真实性,然后比较结果,那么您将获得直觉上假设的结果,即("0" == true) === true。正如道格·克罗克福德(Doug Crockford)在其出色的JavaScript:《好部分》中所说的那样,“ [==强制其操作数类型的规则]复杂而令人难忘……缺乏传递性令人震惊。” 足以说一个操作数被类型强制匹配另一个,并且“ 0”最终被解释为数字零,


1

==相等运算符在将参数转换为数字后对其求值。 因此,将字符串零“ 0”转换为Number数据类型,将布尔值false转换为Number 0

"0" == false // true

同样适用于`

false == "0" //true

===严格相等性检查会评估原始数据类型的参数

"0" === false // false, because "0" is a string and false is boolean

同样适用于

false === "0" // false

if("0") console.log("ha");

字符串“ 0”不与任何参数进行比较,并且字符串是真实值,直到或除非将其与任何参数进行比较。就像

if(true) console.log("ha");

if (0) console.log("ha"); // empty console line, because 0 is false

`


1

这是因为JavaScript在布尔上下文和您的代码中使用类型强制

if ("0") 

在布尔上下文中将被强制为true。

Javascript中还有其他真实值,它们在布尔上下文中会被强制为true,因此执行if块是:

if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.