Rex Overflow Rex Overflow - 5 months ago 29
Javascript Question

Array.length gives incorrect length

If I have an array having object as values at the indices like:

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
alert(a.length); // outputs 91


I have found a workaround to get the actual length:

function getLength(arr) {
return Object.keys(arr).length;
}
var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
alert(getLength(a));


But, why does JS gives incorrect length when objects are stored at random indices? It just adds 1 to the largest index found on an array. Like in the above example, 90 was the largest index. It just adds 1 and gives 91 as output. Demonstration

Answer

That's because length gives you the next index available in the array.

DOCS

arrayLength

If the only argument passed to the Array constructor is an integer between 0 and 2^32-1 (inclusive), this returns a new JavaScript array with length set to that number.

ECMA Specifications

Because you don't have inserted any element in the other keys than 21, 90, 13, all the remaining indexes contains undefined. DEMO

To get actual number of elements in the array:

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};

var len = 0;

for (var i = 0; i < a.length; i++) {
  if (a[i] !== undefined) {
    len++;
  }
}
document.write(len);

Shorter version

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};


for (var i = 0, len = 0; i < a.length; i++, a[i] !== undefined && len++);


document.write(len);

DEMO

EDIT

If the array contains large number of elements, looping to get its length is not the best choice.

As you've mentioned in the question, Object.keys(arr).length is the best solution in this case, considering that you don't have any properties added on that array. Otherwise, the length will not be what you might be expecting.(Thanks To @RobG)