在 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 // number
但NaN === 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?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在html的script标签中写如下代码可以实现javascript脚本的异步加载?
为啥 "true" == true 在 JavaScript 中显示为 false?
为啥 1+ +"2"+3 在 JavaScript 中计算为 6? [复制]