A loosely-typed indexOf()?

2020-04-19 07:25发布

问题:

Let's suppose I have the array:

[1, 2, 3, 4]

Now let's suppose I want to know the first index of a value that ==s (not ===s) a given value, like "3". For this case I would want to return 2, but Array.indexOf returns -1.

:(

回答1:

indexOf does strict equals, so do a conversion on either of the sides, You can try this way:

Either:

arr.map(String).indexOf("3");

or

var str = "3";
arr.indexOf(+str);

Fiddle



回答2:

Well, there's the naive implementation ...

function looseIndex(needle, haystack) {
  for (var i = 0, len = haystack.length; i < len; i++) {
    if (haystack[i] == needle) return i;
  }
  return -1;
}

E.g.

> [0,1,2].indexOf('1')
-1  // Native implementation doesn't match
> looseIndex('1', [0, 1, 2])
1   // Our implementation detects `'1' == 1`
> looseIndex('1', [0, true, 2])
1   // ... and also that `true == 1`

(One bonus of this approach is that it works with objects like NodeLists and arguments that may not support the full Array API.)

If your array is sorted, you can do a binary search for better performance. See Underscore.js' sortedIndex code for an example



回答3:

Perhaps:

function getTypelessIndex(a, v) {
  return a.indexOf(String(v)) == -1)? a.indexOf(Number(v)) : array.indexOf(String(v));
}

But that may do indexOf(String(v)) more than is desirable. To only do the index each way once at most:

function getTypelessIndex(a, v) {
  var index = a.indexOf(String(v));

  if (index == -1) {
    index = a.indexOf(Number(v));
  }
  return index;
}

Note that Array.prototype.indexOf is not supported in IE 9 and lower.