为什么比较一个长度为1的数组的整数返回true而false为长度为2或更多的数组?

时间:2017-06-01 17:53:54

标签: javascript arrays

为什么将0与长度为1的数组进行比较会返回true,而对于数组长度为2或更长的数据,它会返回false? 例如,

var a=[]  //undefined
0<a  //returns false
a.push(1) // [1]
0<a // returns true
a.push(2) // [1, 2]
0<a // return false
a.push(3) // [1, 2, 3]
0<a // return false

7 个答案:

答案 0 :(得分:9)

基本上你会得到一个隐含的类型转换,首先是toString

  

Array对象会覆盖ObjecttoString方法。对于Array对象,toString方法连接数组并返回一个字符串,其中包含用逗号分隔的每个数组元素。

     

当数组要表示为文本值或在字符串连接中引用数组时,JavaScript会自动调用toString方法。

join一样,然后将其转换为数字。

what you do   what you get  result  array        string      number
------------  ------------  ------  ---------    --------    ----------
var a = [];
0 < a         0 < 0         false   []        -> ''       -> 0
a.push(1);
0 < a         0 < 1         true    [1]       -> '1'      -> 1
a.push(2);
0 < a         0 < NaN       false   [1, 2]    -> '1,2'    -> NaN
a.push(3);
0 < a         0 < NaN       false   [1, 2, 3] -> '1,2,3'  -> NaN

答案 1 :(得分:4)

数字和数组之间的比较将触发类型转换。 EcmaScript规范在section 7.1.3中规定了相关规则。根据这些规则,数字不会转换为其他数据类型,但对象(数组是对象)将受到如下转换:

  
      
  1. primValue 为ToPrimitive(参数,提示编号)。
  2.   
  3. 返回号码( primValue )。
  4.   

section 7.1.1中描述了ToPrimitive功能:

  
      
  1. exoticToPrim 成为GetMethod(输入,@ @ toPrimitive)。
  2.   

@@toPrimitive是一个符号,您可以Symbol.toPrimitive访问该符号。问题是Array没有这个属性,所以这个过程继续这个步骤:

  
      
  1. 返回OrdinaryToPrimitive(输入,提示)。
  2.         

    当使用参数O和提示调用抽象操作OrdinaryToPrimitive时,将执行以下步骤:

         
        
    1. 如果提示为“字符串”,则为   一个。让 methodNames 为«“ toString ”,“ valueOf ”»。
    2.   
    3. 否则,
        一个。让 methodNames 为“ valueOf ”,“ toString ”»。
    4.   

由于提示是“数字”,我们处于第二种情况。接下来的步骤说明了这些方法是按顺序应用的。

现在,Array.prototype.valueOf只返回数组本身,因此以下子步骤不会返回,因为Type Object(即Array)。

  

5.c.iii如果Type( result )不是Object,则返回 result

结果是后备启动,并且在数组上调用toString

因此数组转换为字符串。这是顶部列出的两个步骤中的第一个步骤的结果:

  
      
  1. primValue 为ToPrimitive(参数,提示编号)。
  2.   
  3. 返回号码( primValue )。
  4.   

第二步更容易:然后将字符串转换为数字,section 7.1.3.1中对此进行了描述。

Array.prototype.toString方法创建逗号分隔列表时,只要数组有多个元素,这些字符串就会成为无效数字。如规范中所述,返回值为NaN

<的任何NaN比较都会返回false,这会解释您获得的输出。

答案 2 :(得分:1)

如果您在上面的每一行之后将数组检查为数字,则会为您提供所需的答案。 记住javascript在比较期间做了一些类型转换

Number(a); //insert this after each line

答案 3 :(得分:1)

在像JS这样松散类型的语言中,你必须注意像数组这样的可变类型如何强制转换为不可变类型。基本上[1,2]变为"1,2"

所以[1,2] == "1,2" // <- true

答案 4 :(得分:0)

如果您想比较数组的lenght,请使用a.length

答案 5 :(得分:0)

在JS中,如果数组中只有1个元素,js将像元素一样计算他的值,在你的情况下 - 数字。 例如:

var b[]
b.push(8);
b == 8 //true (but b === 8 is false!)

如果数组中有超过1个元素,则数组类型为数组[数字],这与数字不同,因此您无法将其与数字进行比较。

这就是为什么在你做以下代码之后:

var a=[]  
0<a  
a.push(1) 
0<a 

你得到的是,因为a值现在为“1”而且大于0。但是,在下一次推送之后,值为[1,2]并且它不是数字(NaN),这就是为什么你得到假。

答案 6 :(得分:0)

对于比较,javascript尝试通常将操作数转换为数字(首选)。

看看这个例子:

console.log("test" == true);//false
console.log("test" == false);//false

为什么呢?因为“test”试图转换为Number,所以Number(“test”)给出NaN和NaN不等于true或false。 类似地,

0<a becomes 0 < Number(a) becomes 0 < 0 returns "false".

作为一种特殊情况,当数组有一个元素时,Number能够将其强制转换为数字但是当你添加多个元素时,应该返回什么数字? 在这种情况下,Number(arr)变为NaN,并且0再次不小于NaN。