JavaScript数组比较奇怪的行为

时间:2014-03-25 21:45:02

标签: javascript arrays equality ecmascript-5

我试图找出为什么JavaScript在比较同一个数组时有这种奇怪的行为:

var array = [0];
console.log(array == array); //true
console.log(array == !array); //true?

第一个很容易完成,它们引用相同的对象,但第二个是非常棘手的,我正在努力理解这个过程。

请注意,我知道这是abstract equality比较,而不是strict equality比较,我知道他们的差异(我知道使用===会导致{{1} }结果,但我试图找出false)的行为。

P.s。:这个是从wtfjs.com中取出的,我没有找到解释,所以我试着自己给它并认为它可能是“有用的”。

2 个答案:

答案 0 :(得分:2)

第一个相等很简单,它是同一个对象(同一个引用)之间的比较,因此返回true

第二个有点棘手,所以我试着在下面解释一下。

TL; DR

对于那些有点懒惰的人来说,这是一个简单的解释,而不是每一步都引用规范:

[0] == ![0] =>我们首先评估![0],这会产生false(因为[0] truthy 值)。

[0] == false => [0]评估为[0].toString()"0"

"0" == false => "0"转换为0;同样适用于false,因此我们获得:

0 == 0,最后是true

完整解释

至于第一个相等,为了完整起见,我引用了规范中感兴趣的部分。

  

1.f如果x和y引用同一个对象,则返回true。否则,返回false。

所以这会像预期的那样返回true。现在是棘手的部分:

首先,我们必须评估右侧的UnaryExpression

  1. expr 成为评估UnaryExpression的结果。
  2. oldValue ToBoolean GetValue expr ))。
  3. 如果 oldValue 为true,则返回 false
  4. 返回 true
  5. 但是 ToBoolean 使用此algorithm GetValue 应该返回Object或非空String,所以评估结果为 true 。返回我们的UnaryExpression,我们有!true,因此最终评估的结果为false

    所以我们回到原始比较中,现在我们将ObjectBoolean进行比较。

      

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

    ToNumber(false)0,现在我们正在比较ObjectNumber

    返回规格:

      

    9.如果Type(x)是Object而Type(y)是String或Number,则返回比较结果ToPrimitive(x)== y。

    在我们的数组上调用ToPrimitive应返回其[[DefaultValue]],根据this kangax's answer,应该是在数组本身上调用toString的结果,因此我们获得"0"

    因此,回到我们的比较,它已成为StringNumber之间的平等。

      

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

    在我们的字符串"0"上调用ToNumber会产生0,我们再次进行简单的比较:0 == 0

    最终规范步骤:

      

    1.c.iii如果x与y的数值相同,则返回true。

    这里结果解释了。

答案 1 :(得分:0)

algorithm for the == operator从左到右评估表达式,所以给出:

var array = [0];

并评估:

array == !array;

然后首先评估左手表达式并返回一个数组。然后评估右手表达式:ToBoolean应用于数组,因为它是一个对象,它返回 true 和{{1 }}运算符将其反转为 false

然后使用abstract equailty comparison algorithm。同样,首先评估左侧。由于 array 是一个Object而不是Boolean,String或Number,因此使用了第7步,右侧转换为Number,比较变为:

!

算法再次运行并进入步骤9,其中 array 被转换为原语(在本例中为字符串),比较变为:

array == 0;

算法再次运行并进入步骤5,左侧转换为数字,比较变为:

'0' == 0;

算法再次运行,这次表达式具有相同的Type(Number),因此步骤1.iii.c用于返回 true

请注意,通过所有这些,始终首先评估左侧,但有时会导致右侧被修改而不是左侧(例如,在算法的第7步)。