Reputation: 1600
So IE8 doesn't support Array.indexOf()
, so I copied some code that extends the Array prototype so that it is supported and it works.
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (elt /*, from*/) {
var len = this.length >>> 0;
var from = Number(arguments[1]) || 0;
from = (from < 0)
? Math.ceil(from)
: Math.floor(from);
if (from < 0)
from += len;
for (; from < len; from++) {
if (from in this &&
this[from] === elt)
return from;
}
return -1;
};
}
However, I'm running into an issue when I iterate over an array now. Take this for example:
arrayObject = [];
//do some stuff
for(var i in arrayObject) {
...
}
The problem is that after extending the Array prototype, one of the values for i
above is now equal to indexOf
, and the value at that index (i.e. arrayObj[i]
) is equal to the contents of the function. This happens even when the length of the array is zero!! So even when the array is empty, it's still iterating once through for the indexOf
entry.
I realize that I can simply do some type checking in the loop, but I'd rather not do that because I'm retrofitting fallback compatibility onto a large existing project. Is there a way to have the indexOf
array functionality in IE8 without running into this issue?
Upvotes: 3
Views: 86
Reputation: 239683
If at all, you have to use only for..in
to iterate the array, just check if the current item is defined in the Array object, with Object.hasOwnProperty
, like this
var arrayObject = [];
for(var i in arrayObject) {
if (arrayObject.hasOwnProperty(i)) {
...
}
}
Note: As per MSDN's documentation of hasOwnProperty
, it is supported in Internet Explorer 8 Standards mode.
The proper way to define indexOf
would be to make in non-enumerable, like this
Object.defineProperty(Array.prototype, 'indexOf', {
enumerable: false,
configurable: false,
writable: false,
value: function polyFillIndexOf() {...}
});
Since we defined it as non-enumerable, for..in
loop, will not pick the indexOf
property. So, you can still use for..in
with the Array objects (though it is not recommended to do so).
But unfortunately, as per MSDN's documentation of Object.defineProperty
, it works only with DOM objects in IE-8.
Apart from this, when you use for..in
with an Array, you might run in to this inconsistent order of keys problem mentioned in MDN,
Array indexes are just enumerable properties with integer names and are otherwise identical to general Object properties. There is no guarantee that
for...in
will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited.Because the order of iteration is implementation dependent, iterating over an array may not visit elements in a consistent order. Therefore it is better to use a for loop with a numeric index (or
Array.prototype.forEach()
or thefor...of
loop) when iterating over arrays where the order of access is important.
So, the simplest and the best way to do this would be, using simple for
loop, with numeric array indexes, like this
for(var i = 0; i < arrayObject.length; i++) {
console.log(arrayObject[i]);
}
or using Array.prototype.forEach
(which is also supported in Internet Explorer 8 Standards mode), like this
arrayObject.forEach(function(currentItem) {
...
});
PS: Be careful with
arrayObject = [];
you are actually creating a global variable called arrayObject
. You might want to use the var
keyword, like this
var arrayObject = [];
Upvotes: 2
Reputation: 2236
You can use hasOwnProperty to make sure that the i is an index of the array and not a function like indexOf.
for (var i in arrayObject) {
if( arrayObject.hasOwnProperty( i ) ) {
//...
}
}
See docs below for more info:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
That said I'd probably recommend using a counter e.g.
for(var i = 0; i < arrayObject.length; i++) {}
or an each method from a framework like underscore, dojo or jquery etc.. than using a for..in loop like this.
Upvotes: 2