Skip to content Skip to sidebar Skip to footer

What Does A + Prefix Do In This Context?

Here is a line of code from underscore. What is that plus prefix for in this line? if (obj.length === +obj.length) { // plus prefix?

Solution 1:

Adding a + symbol effectively converts a variable into a number, such that:

+"1" === 1;

However, please note that

+"1" === "1"; // FALSE
+"1" ==  "1"; // TRUE

This is because == will convert its operands to the same type, whereas === will not.

That means that the test:

obj.length === +obj.length

Is essentially trying to test whether obj.length is numeric.

In Underscore, this code is trying to figure out if a variable of unknown type has a property called length and whether it is numeric. The assumption is that, if these are both true, you can iterate over the variable is if it were an array.

EDIT

Please note, the OP's code has a number of bugs in it, not least of which is this approach to detecting if something is an Array (or Arraylike). The following object would cause problems:

var footballField = {
    covering: "astroturf",
    condition: "muddy",
    length: 100
};

I'm not advocating the above approach... just explaining someone else's.


Solution 2:

The plus prefix converts the variable into a number. Basically, the obj.length === +obj.length is a sanity check that obj.length really is a number. If the obj.length was not a number, and for example a string "foo", then "foo" === +"foo" would equate to false since +"foo" comes out as NaN.


Solution 3:

This forces the value of obj.length to be a Number. Essentially this is done to make sure that the default length value for an array-like object has not been overridden so that it can be iterated properly.

breaker will do nothing in this context because even another empty object {} will evaluate to false when compared to breaker .. even without an equivalence comparison.

However, breaker is not used in that context because it is defined outside of the .each function, which appears different than what you are showing here. Instead, it is used to force a "break" from other looping methods:

_.every = _.all = function(obj, iterator, context) {
  /* snip */
  if (!(result = result && iterator.call(context, value, index, list)))
      return breaker;

You can see that if the result is not truthy in "every," we want to break immediately. _.every calls _.each, and it will return breaker which will be true when compared to itself, allowing for an immediate break.


Solution 4:

The + prefix converts the value into a number.


Solution 5:

If the object does not have a length property (being a regular Object, instead of an Array), then calling obj.length will return undefined. A test for undefined would be clearer, but the implementor chose to first convert it to a number (so it will become NaN) and then compare it with the original value (using a strict comparison, which will ensure it will yield false).

Update: as others pointed out, this code seems to be concerned not only with Arrays, but also "array-like" objects (i.e. objects that have a numeric length property and numeric indices). In such case, a test for instanceof Array would not be enough (and just testing for undefined might not be the best option, since there could be a length but of another type).


Post a Comment for "What Does A + Prefix Do In This Context?"