Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does (obj.length === +obj.length) compare? [duplicate]

I have been reading underscore.js source code and noticed this compare in _.each():

(obj.length === +obj.length)

I know that + before a variable casts it to a number/integer. So in this cause

[1,2,3].length === +[1,2,3].length

is true. If I pass in an object:

var obj = {a: 1, b: 2, c: 3};

+obj.length produces NaN

In the last case, I have

[1,2,3, {a: [4,5,6]}].length

which is 4. Casting it to a number.. Is still 4.

Deciding from the else case, I can see that this comparation is probably done to distinguish arrays from objects as in else case it uses:

  for (var key in obj) { ...

I fail to see any reason to use such a comparation. Can anyone explain ?

like image 875
lukas.pukenis Avatar asked Jun 08 '26 11:06

lukas.pukenis


2 Answers

Basically, it's a way of testing the type of the length property is Number without using typeof and that the number is not NaN. So in effect:

if (typeof obj.length === "number" && !isNaN(obj.length))

The comparison n === +n will only be true for a number, because === tests both type and value, and +n will create a Number (possibly, as you found, the number NaN). And because NaN === NaN is false, it weeds those out too.

So it's a way of detecting, according to one definition ("has a numeric length that isn't NaN"), whether the object to be iterated is array-like. There are several array-like things in the JavaScript and browser world, such as the arguments pseudo-array and DOM's NodeLists.


Silly performance comparisons:

  • + vs. typeof without worrying about NaN: When true | When false
  • + vs. typeof and isNaN: When true | When false (wrong type) | When false (NaN)

Upshot: Without the NaN aspect, typeof is faster (markedly so when the type is wrong). With the NaN aspect, + is faster when the result will be true and when it will be false because it's NaN, and slower (markedly so) when the result will be false because it's the wrong type. (Opera is, of course, different as always.)

Not that it's likely to matter in the real world (see "silly" above).

like image 160
T.J. Crowder Avatar answered Jun 10 '26 18:06

T.J. Crowder


From the context, I think it's trying to figure out whether obj is an array, since iterating over one would require a sequential for loop rather than for-in: https://stackoverflow.com/a/3010848/367273

like image 37
NPE Avatar answered Jun 10 '26 19:06

NPE