Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is comparing an integer with array of length 1 returns true while false with array of length 2 or more?

Why is comparing 0 with an array of length 1 returns true whereas it returns false for array length of 2 or more ? For example,

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
like image 924
Prateek Avatar asked Jun 01 '17 17:06

Prateek


3 Answers

Basically you get a implicid type conversion, first toString,

The Array object overrides the toString method of Object. For Array objects, the toString method joins the array and returns one string containing each array element separated by commas.

JavaScript calls the toString method automatically when an array is to be represented as a text value or when an array is referred to in a string concatenation.

like join works and then it is converted to number.

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
like image 40
Nina Scholz Avatar answered Oct 20 '22 11:10

Nina Scholz


The comparison between a number and an array will trigger a type conversion. The EcmaScript specification sets out the rules for this in section 7.1.3. According to these rules, the number is not converted to another data type, but the object (an array is an object) will be subject to a conversion that goes like this:

  1. Let primValue be ToPrimitive(argument, hint Number).
  2. Return ToNumber(primValue).

The ToPrimitive function is described in section 7.1.1:

  1. Let exoticToPrim be GetMethod(input, @@toPrimitive).

@@toPrimitive is a Symbol, which you access as Symbol.toPrimitive. The thing is that Array does not have this property, and so the process continues with this step:

  1. Return OrdinaryToPrimitive(input,hint).

When the abstract operation OrdinaryToPrimitive is called with arguments O and hint, the following steps are taken:

  1. If hint is "string", then
        a. Let methodNames be «"toString", "valueOf"».
  2. Else,
        a. Let methodNames be «"valueOf", "toString"».

As the hint is "number", we are in the second case. The next steps explain that these methods are applied in order.

Now, Array.prototype.valueOf just returns the array itself, so the following sub-step will not return, since the Type is Object (namely Array).

5.c.iii If Type(result) is not Object, return result.

As a consequence the fallback kicks in, and toString is called on the Array.

So the array is converted to string. This is the result of the first of the two steps listed at the top:

  1. Let primValue be ToPrimitive(argument, hint Number).
  2. Return ToNumber(primValue).

The second step is easier: the string is then converted to number, which is described in section 7.1.3.1.

As the Array.prototype.toString method creates a comma-separated list, these strings become certainly invalid numbers as soon as an array has more than one element. As mentioned in the specs, the return value then is NaN.

Any < comparison with NaN returns false, which explains the output you get.

like image 73
trincot Avatar answered Oct 20 '22 13:10

trincot


In a loosely typed language like JS you have to pay attention to how a mutable type like an array coerces into an immutable type. Basically [1,2] becomes "1,2".

So [1,2] == "1,2" // <- true

like image 35
Redu Avatar answered Oct 20 '22 11:10

Redu