"0"
被视为假(false):>>> "0" == false
true
>>> false == "0"
true
所以为什么以下代码会输出 "ha"
?>>> if ("0") console.log("ha")
ha
"0"
被视为假(false):>>> "0" == false
true
>>> false == "0"
true
所以为什么以下代码会输出 "ha"
?>>> if ("0") console.log("ha")
ha
typeof NaN // number
但是 NaN === NaN // false
,嗯... - Justus Romijn[]
、{}
、[[]]
、[0]
和[1]
的值,既无==
操作符也无===
操作符会得出真值。我是说[] == []
和 [] === []
也是假的。 - Herbertusz原因是当你显式地执行"0" == false
时,双方都被转换为数字,然后进行比较。
而当你执行 if ("0") console.log("ha")
时,测试的是字符串值。任何非空字符串都是 true
,而空字符串则是 false
。
等于(==)
如果两个操作数类型不同,JavaScript 将转换操作数再执行严格比较。如果任一操作数是数字或布尔值,则将它们转换为数字(如果可能);否则,如果任一操作数是字符串,则将另一个操作数转换为字符串(如果可能)。如果两个操作数都是对象,则 JavaScript 比较内部引用,仅当操作数引用内存中的同一对象时才相等。
(摘自 Mozilla 开发者网络上的比较运算符)
这是技术规范的要求。
12.5 if语句 .....
2. 如果 ToBoolean(GetValue(exprRef)) 为true, 则 a. 返回第一个语句的评估结果。 3. 否则, ....
ToBoolean在规范中的定义为:
ToBoolean是抽象操作,根据表11将其参数转换为布尔类型的值:
这个表格对字符串的说明如下:
如果参数是空字符串(长度为零),则结果为false;否则结果为true
现在,为什么"0" == false
需要解释,你需要阅读相等运算符,它表明它从左侧和右侧都匹配为抽象操作GetValue(lref)
的值。
这个相关部分的描述如下:
如果IsPropertyReference(V)为真,则 a. 如果HasPrimitiveBase(V)为假,则让get成为base的[[Get]]内部方法, 否则让get成为下面定义的特殊[[Get]]内部方法。 b. 使用base作为其this值调用get内部方法的结果,并将GetReferencedName(V)作为参数传递返回
换句话说,字符串有一个原始基础,它调用内部的get方法,最终看起来是false。
如果要使用GetValue操作评估表达式,请使用==
,如果要使用ToBoolean
进行评估,请使用===
(也称为“严格”相等运算符)。
Section 8.12.3: [[Get]] (P)
描述了它的工作原理。只有在字符串为0的情况下才是正确的,因为它最终会调用一堆其他的内部调用,最终导致GetOwnProperty
看到“whatever”是一个数据属性,然后返回该值。这就是为什么“0”为假,“blah”为真的原因。请查看Douglas Crockford在Yahoo开发者剧院中的一些视频,他比我更简单地描述了JavaScript中的“truthyness”。如果你理解了“truthy”和“falsy”的含义,你就能立刻理解Bobince的答案。 - Incognito这里提到的是PHP中的字符串"0"
是falsy(在布尔上下文中使用时为false)。而在JavaScript中,所有非空字符串都是truthy。
问题在于,对布尔值进行==
比较时并不是在布尔上下文中进行的,而是将其转换为数字。对于字符串而言,它会被解析为十进制数字,因此你得到的是数字0
而不是truthiness布尔值true
。
这是一种非常糟糕的语言设计,这也是我们尽量不使用不幸的==
运算符的原因之一。应该使用===
代替。
// 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.
你在0
周围加上引号,这使它成为了一个字符串,被解释为true。
移除引号,它就可以正常工作。
if (0) console.log("ha")
== 等于运算符会将参数转换为数字后再进行比较。因此,字符串零“0”会被转换为数字类型,布尔值false会被转换为数字0。
"0" == false // true
同样适用于:
false == "0" //true
=== 严格相等运算符会保留原始数据类型,对参数进行比较。
"0" === false // false, 因为"0"是字符串而false是布尔值
同样适用于:
false === "0" // false
在
if("0") console.log("ha");
字符串“0”并不与任何参数进行比较,只有在与其他参数进行比较时才会被视为真值。这就像
if(true) console.log("ha");
但是
if (0) console.log("ha"); // 空的控制台行,因为0是假值
这就是为什么尽可能使用严格相等 ===
或严格不等 !==
"100" == 100
true
,因为它只检查值,而不是数据类型
"100" === 100
false
,因为它检查值和数据类型
"0" == false
是因为在此处指定的规则http://ecma262-5.com/ELS5_HTML.htm#Section_11.9.3。而if ('0')
计算结果为true,是因为在此处指定的规则http://ecma262-5.com/ELS5_HTML.htm#Section_12.5。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)
"0" === false [...] false
- user1385191'0'==false
但是 '0' 不是假值(是的,JavaScript 可能很奇怪) - Linsey==
比较两个值时,它们永远不会被转换为布尔值,因此这个概念不适用。(这种转换规则更倾向于将值转换为数字。) - millimoose