Array Expansion Issue in IE8
So IE8 doesn't support Array.indexOf()
, so I copied some code that extends the Array prototype to be 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 ran into a problem when I now iterate over the array. 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 indexOf
, and the value at that index (i.e. arrayObj[i]
) is equal to the content of the function.This happens even when the length of the array is zero! Therefore, even when the array is empty, it is still iterated over for writing indexOf
.
I realize that I can just do some type checking in a loop, but I would rather not do this because I am upgrading fallback compatibility with a large existing project. Is there a way to have array functionality indexOf
in IE8 without facing this issue?
source to share
You can use hasOwnProperty to make sure i is an array index and not an indexOf function.
for (var i in arrayObject) {
if( arrayObject.hasOwnProperty( i ) ) {
//...
}
}
See docs below for more information:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in
This says that I probably recommend using a counter for example.
for(var i = 0; i < arrayObject.length; i++) {}
or every method from a framework like underscore, dojo or jquery etc. than using a for..in loop like this.
source to share
If you only need to use for..in
to iterate over an array at all, just check if the current element is defined in the Array object, with Object.hasOwnProperty
like this
var arrayObject = [];
for(var i in arrayObject) {
if (arrayObject.hasOwnProperty(i)) {
...
}
}
Note. ... According to MSDN documentationhasOwnProperty
, it is supported in Internet Explorer 8 Standards mode.
The correct way to define indexOf
should be in a non-enumerable form, for example
Object.defineProperty(Array.prototype, 'indexOf', {
enumerable: false,
configurable: false,
writable: false,
value: function polyFillIndexOf() {...}
});
Since we have defined it as a non-enumerable loop for..in
, it will not select a property indexOf
. This way you can still use for..in
with Array objects (although not recommended).
But unfortunately, according to the MSDN documentationObject.defineProperty
, it only works with DOM objects in IE-8.
Also, when you use for..in
with an array, you can run this inconsistent key order mentioned in MDN ,
Array indices are simply enumerated properties with integer names and are otherwise identical to general object properties. There is no guarantee that it
for...in
will return indexes in any particular order and will return all enumerated properties, including those with non-integer names and inheritance.Since the order of iteration is implementation dependent, iterating over an array may not visit the elements in sequential order. Therefore, it is better to use a for loop with a numeric index (or
Array.prototype.forEach()
or loopfor...of
) when iterating over arrays where the sequence of access is important.
So, the simplest and best way to do it is to use a simple loop for
with numeric array indices, like
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
arrayObject.forEach(function(currentItem) {
...
});
PS: Be careful with
arrayObject = [];
you are actually creating a global variable named arrayObject
. You might want to use a keyword var
like
var arrayObject = [];
source to share