1

Looking into Underscore.js code and more specifically into _.indexOf() function (find code with comments here)

_.indexOf = function(array, item, isSorted) {
    var i = 0, length = array && array.length;
    if (typeof isSorted == 'number') {
      i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
    } else if (isSorted && length) {
      i = _.sortedIndex(array, item);
      return array[i] === item ? i : -1;
    }
    if (item !== item) {
      return _.findIndex(slice.call(array, i), _.isNaN);
    }
    for (; i < length; i++) if (array[i] === item) return i;
    return -1;
};

I noticed the if(item !== item){...} statement, but I don't get its purpose. items is a parameter and it's not changed inside the function. When would a variable differ from itself?

Am I missing something?

JJJ
  • 32,902
  • 20
  • 89
  • 102
BeNdErR
  • 17,471
  • 21
  • 72
  • 103

2 Answers2

4

IEEE-754 NaNs are not equal to themselves. The if statement is checking whether item is a NaN. If it is, the function needs to use special logic since the search loop testing for array[i] === item won't work.

For further discussion, see Why is NaN not equal to NaN? and What is the rationale for all comparisons returning false for IEEE754 NaN values?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
2

The number constant NaN is never === to another value, including itself. Thus that's a way to test for NaN without a function call. Absolutely any other value of item would test equal to itself:

  • undefined is === to undefined
  • null is === to null
  • a number is equal to itself, as is a string or a boolean
  • a reference to an object is === to itself (and only to itself!)
Pointy
  • 405,095
  • 59
  • 585
  • 614