为什么两个if('0'== false)和if('0')在Javascript中评估为true?

时间:2013-05-08 21:46:29

标签: javascript if-statement

因此我知道Javascript中的if语句将其条件的结果转换为布尔值,然后执行它,如下所示

if(true) {
    // run this
}

if(false) {
    // do not run this
}

这很有效。但如果我这样做:

if('0' == false) {
    // We get here, so '0' is a falsy value
}

然后我会期待这个

if('0') {
    // We don't get here, because '0' is falsy value
}

但我得到了

if('0') {
    // We *DO* get here, even though '0' is falsy value
}

那发生了什么事?显然,if不会检查其条件是否为真值或假值,而是进行其他转换?

4 个答案:

答案 0 :(得分:7)

这只是== rules中那些相当复杂的“陷阱”之一。

  

比较x == y,其中x和y是值,产生true或false。这样的比较如下进行:

     

(4)如果Type(x)是Number而Type(y)是String,   返回比较结果x == ToNumber(y)。

     

(5)如果Type(x)是String而Type(y)是Number,   返回比较结果ToNumber(x)== y。

     

(6)如果Type(x)是布尔值,则返回比较结果ToNumber(x)== y。

     

(7)如果Type(y)是布尔值,则返回比较结果x == ToNumber(y)。

在这种情况下,这意味着'0' == false首先被强制执行'0' == 0(通过规则#7),然后在第二次传递时,它被强制执行0 == 0(按规则# 5)结果是真的。

由于false ~> 0而不是'0' ~> true(可能是预期的),这个特例非常棘手。但是,'0'本身就是一个真值,并且行为可以用上述规则来解释。要在测试中使用严格的truthy-falsey相等(不同于严格相等)而不在相等期间进行隐式转换,请考虑:

!!'0' == !!false

(适用于所有值:!falsey -> true!truthy -> false。)

答案 1 :(得分:3)

此:

if('0') {
    // We *DO* get here, even though '0' is falsy value
}

检查字符串是空还是空,而不是它是否为零。任何非空字符串都是真实的。

执行此操作时:

if('0' == false) {
    // We get here, so '0' is a falsy value
}

您要求JS引擎进行显式类型转换以尝试匹配两个操作数的类型。这不仅仅是询问一个操作数本身是否真实。

一般情况下,如果您几乎总是使用===!==,并且只知道在所有情况下确实会发生什么,只会因为类型强制,您会发现意外结果会更少你完全理解非常复杂的强制规则,或者因为你知道会出现什么类型,并且你理解这些特定情况。

答案 2 :(得分:3)

if ('0' == false)

Javascript正在做一些名为type coercion的事情。

遵循该链接中的规则,我们将遵循规则7:

  

如果Type(y)是布尔值,则返回比较结果x == ToNumber(y)

调用ToNumber(false)给我们一个数字0.结果现在开始有意义,但我们还没有完成,因为我们仍然有一个字符串和一个数字。这个过程再次开始,这次我们归结为规则5:

  

如果Type(x)是String而Type(y)是Number,则返回比较结果ToNumber(x)== y:“2”== 2

这次,左侧'0'被转换为数字:0。现在,我们最后可以比较两个数字,并且由于0等于0,结果为真。但是,重要的是要注意,这对于'0'字符串的完整/虚假性质一无所知,因为它在被比较之前就被强制了。

if('0')

在这种情况下,没有比较;你只想知道单个值是“truish”还是“falsy”。没有使用类型强制,因为字符串可以根据其自身的优点被评估为truish或falsy。使用与以前相同的链接规则,我们可以找到以下信息:

  

在JavaScript中,不仅是JavaScript,我们还有所谓的虚假值。它们分别是:0,null,undefined,false,“”,NaN。请注意空字符串是空的,因为不同于php的例子,“0”将被认为是真实的

引用特别有用,因为它专门调用'0'字符串,但这不是必需的。足以知道空字符串是假的,并且任何其他字符串都是完整的,因为不评估字符串的内容并且不执行强制。 0可能是一个假值,但是因为我们评估一个字符串而不是强制转换为一个数字,而'0'具有某种值,所以它仍然是真实的。

答案 3 :(得分:1)

Javascript运算符==进行类型转换,基本上没用。只是避免它。

例如:

  • []是truty但[] == false true
  • 1 == "1"[1] == "1"[[1]] == "1"都是真的
  • [1] == [[1]]但是错误

规则非常奇怪。例如,在第一种情况下,[]转换为"",转换为数字,值为0false也会转换为0。所以最后他们比较平等。

但请注意,虽然从空字符串到数字的转换为0,但parseInt("")的结果为NaN

PS:真正有趣的是当你发现[30,20,10,3,2,1].sort()返回[1,10,2,20,3,30]时(是......数字,按字典顺序排列是)。不,我不是在开玩笑。