简体   繁体   中英

Comparison array number in JS

I'm working with JS and I don't understand certain behavior with arrays. I searched but I can't find a correct answer, so sorry if this is dupe or in relation with another question.

I have the following code using lodash.

    return _.difference(self.list1, self.list2) <= 0;

That is returning an array and I'm comparing it directly with a number, just because I forgot the .length property. I saw that this is "working" unless it is not correct. So I started to do some tests with the JS console and I don't understand what is happening here.

[Object, Object, Object] <= 0 //returns false

[] <= 0 //returns true

[[]] <= 0 //returns true

[[[]]] <= 0 //returns true

[[2]] <= 0 // returns false

[[],[]] <= 0 //returns false

What is JS doing here? Thank you very much.

The <= operator will coerce its operands to try to make them comparable. The full details are in the specification's Abstract Relational Comparison operation , but basically:

When you compare an object reference with a primitive, it tries to convert the referenced object to a primitive. In this case, since the primitive is a number, it will try to get a primitive number from the object if the object supports that (arrays don't) and then fall back on getting a string. At which point it has a string and a number, so it coerces the string to number and compares them numerically.

When you convert an array to a string, it does the same thing join does: Joins the string version of all the entries together separated by commas. Of course, if you have only one entry, you'll end up with just that entry (as a string).

Here's a simpler example:

 var a = [2]; console.log(a < 10); // true 

The steps there are:

  1. Since a contains an object reference, convert that object to a primitive, preferring a number to a string if possible:

    • Arrays don't provide a way of converting to number, so we end up doing (effectively) a.toString()
    • a.toString() calls a.join() , which joins the entries together as strings with a comma in between
    • So we end up with "2" .


    Now we have "2" < 10

  2. Since one of those is a number, the operator coerces the other one to number, giving us 2 < 10

  3. The result of 2 < 10 is true

This strategy sometimes, even frequently, means the <= operator ends up comparing NaN to something. For instance, if a were a non-array object:

 var a = {}; console.log(a.toString()) // "[object Object]" console.log(a < 10); // false 

The steps would be:

  1. Since a contains an object reference, convert that object to a primitive, preferring a number to a string if possible:

    • Plain objects don't support conversion to number, so we end up doing (effectively) a.toString() .

    • As you can see in the snippet above, that gives us "[object Object]"


    Now we have "[object Object]" < 10

  2. Since one of those is a number, the operator coerces the other one to number. "[object Object]" coerced to a number is NaN .

  3. The result of NaN < 10 is false , because all comparisons involving NaN (including === ) result in false . (Yes, really; NaN === NaN is false .)

(Thanks Rajesh for suggesting the {} < 10 example and providing the initial version of the above.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM