11

I was perusing the underscore.js library and I found something I haven't come across before:

if (obj.length === +obj.length) { ... }

What is that + operator doing there? For context, here is a direct link to that part of the file.

JoeM05
  • 904
  • 1
  • 9
  • 27
  • 1
    possible duplicate of [Whats the significant use of Unary Plus and Minus operators?](http://stackoverflow.com/questions/5450076/whats-the-significant-use-of-unary-plus-and-minus-operators) – Daniel A. White Nov 30 '11 at 17:50
  • It is another way to convert strong to number. You can play with it here http://jsfiddle.net/wbednarski/uCm93/ – Wojciech Bednarski Nov 30 '11 at 18:00
  • It does seem a little strange to use `===` with a type conversion. – jfriend00 Nov 30 '11 at 18:00
  • @jfriend00 A little bit. However I think they use `===` by convention everywhere and it is good practice. – Wojciech Bednarski Nov 30 '11 at 18:02
  • @DanielA.White It's kinda a duplicate, but I think the question is useful as unless you already know what a 'unary plus operator' is you wouldn't find the other question. – Ben Clayton Nov 30 '11 at 18:49

4 Answers4

7

The unary + operator can be used to convert a value to a number in JavaScript. Underscore appears to be testing that the .length property is a number, otherwise it won't be equal to itself-converted-to-a-number.

Jeremy
  • 1
  • 77
  • 324
  • 346
  • Also note(in case others find this answer in the future), in addition to the accepted answer, that the specific code in underscore.js is being used to check if the passed in obj is an array. obj as array in this context returns true, obj as object returns false. – Cooper Buckingham Jan 24 '15 at 01:55
4

According to MDN:

The unary plus operator precedes its operand and evaluates to its operand but attempts to converts it into a number, if it isn't already. For example, y = +x takes the value of x and assigns that to y; that is, if x were 3, y would get the value 3 and x would retain the value 3; but if x were the string "3", y would also get the value 3. Although unary negation (-) also can convert non-numbers, unary plus is the fastest and preferred way of converting something into a number, because it does not perform any other operations on the number. It can convert string representations of integers and floats, as well as the non-string values true, false, and null. Integers in both decimal and hexadecimal ("0x"-prefixed) formats are supported. Negative numbers are supported (though not for hex). If it cannot parse a particular value, it will evaluate to NaN.

FishBasketGordo
  • 21,938
  • 4
  • 54
  • 88
3

It's a way of ensuring that obj.length is a number rather than a potential string. The reason for this is that the === will fail if the length (for whatever reason) is a string variable, e.g. "3".

Ben Clayton
  • 75,781
  • 25
  • 117
  • 124
2

It's a nice hack to check whether obj.length is of the type number or not. You see, the + operator can be used for string coercion. For example:

alert(+ "3" + 7); // alerts 10

This is possible because the + operator coerces the string "3" to the number 3. Hence the result is 10 and not "37".

In addition, JavaScript has two types of equality and inequality operators:

  1. Strict equality and inequality (e.g. 3 === "3" expresses false).
  2. Normal equality and inequality (e.g. 3 == "3" expresses true).

Strict equality and inequality doesn't coerce the value. Hence the number 3 is not equal to the string "3". Normal equality and inequality does coerce the value. Hence the number 3 is equal to the string "3".

Now, the above code simply coerces obj.length to a number using the + operator, and strictly checks whether the value before and after the coercion are the same (i.e. obj.length of the type number). It's logically equivalent to the following code (only more succinct):

if (typeof obj.length === "number") {
    // code
}
Aadit M Shah
  • 67,342
  • 26
  • 146
  • 271
  • 2
    A subtle difference between `obj.length === +obj.length` and `typeof obj.length === "number"` is that the `typeof` check would return true for `NaN`, where comparing to itself as a number wouldn't (`NaN` is not equal to itself). – Matthew Crumley Nov 30 '11 at 20:02
  • @MatthewCrumley - I never understood why so. Is it because there are two kinds of `NaN`: quiet and signaling? Or perhaps because `NaN` values are treated as objects? – Aadit M Shah Nov 30 '11 at 20:22
  • I think it's because logically, you can't say that any two values that aren't numbers must be equal. It also keeps expressions like `Math.sqrt(-1) === Math.sqrt(-2)` from evaluating to true. – Matthew Crumley Nov 30 '11 at 20:30