在 JavaScript 中,为啥 "0" 等于 false,但是当通过 'if' 测试时,它本身不是 false?

Posted

技术标签:

【中文标题】在 JavaScript 中,为啥 "0" 等于 false,但是当通过 \'if\' 测试时,它本身不是 false?【英文标题】:In JavaScript, why is "0" equal to false, but when tested by 'if' it is not false by itself?在 JavaScript 中,为什么 "0" 等于 false,但是当通过 'if' 测试时,它本身不是 false? 【发布时间】:2011-11-28 17:39:59 【问题描述】:

以下说明"0"javascript中为假:

>>> "0" == false
true

>>> false == "0"
true

那么为什么下面会打印"ha"

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

【问题讨论】:

"0" 是一个字符串,因为它不为空,所以它被评估为真。 "0" === false [...] false 查看 Angus Croll 的 javascript 文章真相。 javascriptweblog.wordpress.com/2011/02/07/… '0'==false 但 '0' 不是虚假值(是的,Javascript 可能很奇怪) @Linsey:整个“虚假”和“真实”的事情只是为了解释如何将值转换为布尔值。当您将两个值与 == 进行比较时,它们从不被转换为布尔值,因此它不适用。 (转换规则似乎有利于转换为数字。) 【参考方案1】:

显示问题的表格:

和 ==

故事的寓意使用 ===

表生成信用:https://github.com/dorey/JavaScript-Equality-Table

【讨论】:

使用另一个值顺序更有意义gist.github.com/kirilloid/8165660 从现在开始,如果有人说他从不使用严格的比较运算符,我会用这些表来面对他,让他哭。不过,我仍然不确定我是否掌握了NaN 的概念。我的意思是,typeof NaN // numberNaN === NaN // false,嗯... 我的一个朋友制作了f.cl.ly/items/3b0q1n0o1m142P1P340P/javascript_equality.html - 与上面的图表相同,但更易于阅读。 @JustusRomijn 有多个值来表示NaN,因此当您比较 2 个 NaN 时,它们具有不同的值(我猜)。阅读第一句话here。 这些表有错误。对于 [][[]][0][1] 值,===== 运算符均不会评估为真。我的意思是[] == [][] === [] 也是错误的。【参考方案2】:

原因是因为当你显式做"0" == false时,两边都被转换成数字,然后然后进行比较。

当你这样做时:if ("0") console.log("ha"),字符串值正在被测试。任何非空字符串都是true,而空字符串是false

相等 (==)

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

(来自 Mozilla 开发者网络中的 Comparison Operators)

【讨论】:

【参考方案3】:

这是根据规范。

12.5 if 语句 ...... 2. 如果 ToBoolean(GetValue(exprRef)) 为真,则 一种。返回评估第一条语句的结果。 3. 否则, ……

根据规范,ToBoolean 是

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

该表说明了字符串:

如果参数是空字符串(其长度为零),则结果为假; 否则结果为真

现在,要解释为什么 "0" == false 应该阅读相等运算符,它指出它从抽象操作 GetValue(lref) 中获取其值,与右侧相同。

将相关部分描述为:

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

或者换句话说,一个字符串有一个原始基,它回调内部的get方法并最终看起来是假的。

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

【讨论】:

"a string has a primitive base, which calls back the internal get method and ends up looking false" 所有字符串都是这样吗? @Interstellar_Coder Section 8.12.3: [[Get]] (P) 描述了它是如何工作的。仅适用于字符串为 0 的情况,因为它执行了一堆其他内部调用,最终导致 GetOwnProperty 看到“whatever”是一个数据属性,然后一直返回该值。这就是为什么“0”是假的,而“blah”是真的。查看一些 Douglas Crockford 在 Yahoo 开发者剧场上的视频,他用 JavaScript 描述的“真实性”比我简单一点。如果您了解“真实”和“虚假”的含义,您将立即理解 Bobince 的回答。 在哪里可以找到规范?【参考方案4】:

php 中,字符串 "0" 是假的(false-when-used-in-boolean-context)。在 JavaScript 中,所有非空字符串都是真值。

诀窍在于 == 对布尔值不会在布尔上下文中进行评估,它会转换为数字,并且对于通过解析为十进制来完成的字符串。所以你得到数字0而不是真实性布尔值true

这是一个非常糟糕的语言设计,这也是我们尽量不使用不幸的== 运算符的原因之一。请改用===

【讨论】:

【参考方案5】:
// 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.

【讨论】:

【参考方案6】:

0 周围的引号使它成为一个字符串,它被评估为 true。

删除引号,它应该可以工作。

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

【讨论】:

正确,不是关于如何“让它工作”,而是问题更像是,“为什么它会这样?” 有趣的是,这么多年过去了,正确的答案就在这里,却很少有人注意到。 @JasonGennaro,谢谢你没有忽略显而易见的事情。【参考方案7】:

这完全是因为 ECMA 规范 ..."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

【讨论】:

我不知道有人将规范移植到网站...太棒了!我不再需要 PDF。【参考方案8】:

== 等式运算符在将参数转换为数字后对其进行评估。 所以字符串零“0”被转换为数字数据类型,布尔假被转换为数字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

`

【讨论】:

【参考方案9】:

“if”表达式测试真实性,而 double-equal 测试与类型无关的等效性。正如其他人在这里指出的那样,字符串总是真实的。如果双等号测试其两个操作数的真实性,然后比较结果,那么您将得到您直观假设的结果,即("0" == true) === true。正如 Doug Crockford 在其出色的 JavaScript: The Good Parts 中所说,“[== 强制其操作数的类型] 的规则复杂且难以记忆……缺乏传递性令人担忧。 "只要说其中一个操作数被强制类型匹配以匹配另一个就足够了,并且“0”最终被解释为数字零,当强制为布尔值时,它又相当于 false(或者 false 相当于零强制转换为数字时)。

【讨论】:

【参考方案10】:

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

if ("0") 

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

Javascript 中还有其他真值,在布尔上下文中将被强制为真,因此执行 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)

【讨论】:

【参考方案11】:

这就是为什么您应该尽可能使用严​​格相等 === 或严格不等式 !==

"100" == 100

true 因为它只检查值,而不是数据类型

"100" === 100

false 检查值和数据类型

【讨论】:

【参考方案12】:
if (x) 

使用 JavaScript 的内部 toBoolean (http://es5.github.com/#x9.2) 强制 x

x == false

使用内部 toNumber 强制 (http://es5.github.com/#x9.3) 或对象的 toPrimitive (http://es5.github.com/#x9.1) 强制双方

详情请见http://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

【讨论】:

【参考方案13】:

我有同样的问题,我找到了一个可行的解决方案如下:

原因是

    if (0) means false, if (-1, or any other number than 0) means true. following value are not truthy, null, undefined, 0, ""empty string, false, NaN

永远不要使用像 id 这样的数字类型

      if (id) 

对于可能值为 0 的 id 类型,我们不能使用 if (id) ,因为 if (0) 将意味着 false、invalid,我们希望它意味着作为 true id 号有效。

所以对于id类型,我们必须使用如下:

   if ((Id !== undefined) && (Id !== null) && (Id !== ""))
                                                                                
                                                                             else 

                                                                            
                                                                            

对于其他字符串类型,我们可以使用 if (string) ,因为 null、undefined、empty string 都将评估为 false,这是正确的。

       if (string_type_variable)  

【讨论】:

【参考方案14】:

在 JS 中“==”符号不检查变量的类型。因此,"0" = 0 = false(在 JS 中为 0 = false)并且在这种情况下会返回 true,但如果你使用 "===" 结果将是 false。

当你使用“if”时,在以下情况下会是“false”:

[0, false, '', null, undefined, NaN] // null = undefined, 0 = false

所以

if("0") = if( ("0" !== 0) && ("0" !== false) && ("0" !== "") && ("0" !== null) && ("0" !== undefined) && ("0" !== NaN) )
        = if(true && true && true && true && true && true)
        = if(true)

【讨论】:

以上是关于在 JavaScript 中,为啥 "0" 等于 false,但是当通过 'if' 测试时,它本身不是 false?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 JavaScript 中的 "0" == "" 为假

为啥在html的script标签中写如下代码可以实现javascript脚本的异步加载?

为啥 "true" == true 在 JavaScript 中显示为 false?

为啥 1+ +"2"+3 在 JavaScript 中计算为 6? [复制]

为啥 [1,2] + [3,4] = "1,23,4" 在 JavaScript 中?

javascript,innerHTML或者innerText获取的内容是否字符串?为啥和另外一个字符串相比结果不对