4

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

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

4 回答 4

7

这只是==规则相当复杂的“陷阱”之一。

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

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

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

(6) 如果 Type(x) 是 Boolean,返回比较结果 ToNumber(x) == y。

(7) 如果 Type(y) 为 Boolean,则返回比较结果 x == ToNumber(y)。

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

这种特殊情况有点棘手,因为false ~> 0而不是'0' ~> true(正如预期的那样)。但是,'0'它本身就是一个真值,并且可以用上述规则解释该行为。要在测试中具有严格的真假相等(这与严格相等不同)而在相等期间没有隐式转换,请考虑:

!!'0' == !!false

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

于 2013-05-08T21:56:04.553 回答
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 引擎进行显式类型转换以尝试匹配两个操作数的类型。这与仅仅询问一个操作数本身是否真实不同。

一般来说,如果您几乎总是使用===并且!==仅在您确切知道在所有情况下会发生什么时才允许类型强制,您会发现您得到的意外结果更少,因为您完全了解非常复杂的强制规则,或者因为您知道什么类型将出现,您了解这些特定情况。

于 2013-05-08T21:48:06.780 回答
3

if ('0' == false)

Javascript 正在做一些名为type coercion.

按照该链接中的规则,我们属于规则 7:

如果 Type(y) 为 Boolean,则返回比较结果 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')

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

在 JavaScript 中,不仅仅是 JavaScript,我们有所谓的虚假值。它们分别是:0、null、undefined、false、""、NaN。请注意,空字符串是空的,因为与 php 不同,例如,“0”将被视为 truish

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

于 2013-05-08T21:53:59.387 回答
1

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

例如:

  • []是真实的,但是[] == false真实的
  • 1 == "1", [1] == "1",[[1]] == "1"都是真的
  • [1] == [[1]]然而是假的

规则很奇怪。例如,在第一种情况下[]被转换为""被转换为数字并且值为0. false也转换为数字0。所以最后他们比较相等。

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

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

于 2013-05-08T22:04:43.300 回答