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)

Answer from Tushar on Stack Overflow
Top answer
1 of 4
19

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)

2 of 4
6

The array in JavaScript is a simple zero-based structure. The array.length returns the n + 1 where n is the maximum index in an array.

That's just how it works - when you assign 90'th element and this array's length is less than 90, it expands an array to 90 and sets the 90-th element's value. All missing values are interpreted as null.

If you try the following code:

var a = [];
a[21] = {};
a[90] = {};
a[13] = {};
console.log(JSON.stringify(a));

You will get the following JSON:

[null,null,null,null,null,null,null,null,null,null,null,null,null,{},null,null,null,null,null,null,null,{},null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,{}]

Moreover, array.length is not a readonly value.
If you set a length value less than the current, then the array will be resized:

 var arr = [1,2,3,4,5];
 arr.length = 3;
 console.log(JSON.stringify(arr));
 // [1,2,3]

If you set a length value more than the current, then the array will be expanded as well:

 var arr = [1,2,3];
 arr.length = 5;
 console.log(JSON.stringify(arr));
 // [1,2,3,null,null]

In case you need to assign such values, you can use JS objects.
You can use them as associative array and assign any key-value pairs.

var a = {};
a[21] = 'a';
a[90] = 'b';
a[13] = 'c';
a['stringkey'] = 'd';
a.stringparam = 'e'; // btw, a['stringkey'] and a.stringkey is the same

console.log(JSON.stringify(a)); 
// returns {"13":"c","21":"a","90":"b","stringkey":"d","stringparam":"e"}

console.log(Object.keys(a).length);
// returns 5
Discussions

node.js - Array length is not correct in javascript - Stack Overflow
Generally it's not a good idea to add string keys to an array - but if you do need to use them, then no, they don't affect the automatically-updated length property. ... .length is a special property in Javascript arrays, which is defined as "the biggest numeric index in the array plus one" ... More on stackoverflow.com
🌐 stackoverflow.com
Javascript array length incorrect on array of objects - Stack Overflow
Object isn't really a proper associative-array is JavaScript; you can mostly use it as if it is, but there are pitfalls. 2010-03-27T12:23:42.27Z+00:00 ... Object is not an Array at all. Teh confusion comes because one way to assign a property is via the a[b] syntax...but its no different from saying a.b 2010-03-27T16:08:55.03Z+00:00 ... +1 - Very nice explanation. It makes sense about the length ... More on stackoverflow.com
🌐 stackoverflow.com
March 27, 2010
javascript - Array length incorrect - Stack Overflow
You are correct. I think the array is being changed between the time I logged it and the time I opened it. Your solution seems to work. Marking it as an answer in a min. :) ... The problem is probably that the array changed between the time you logged it and the time you opened it in the console. ... Note ... More on stackoverflow.com
🌐 stackoverflow.com
July 4, 2016
JavaScript array length issue - Stack Overflow
When I do a console.log of two different arrays, one is giving me the actual length but not the other. ... [A: Object, B: Object, C: Object, D: Object] A: Object B: Object C: Object D: Object length: 0 __proto__: Array[0] Why do my first array do have a correct length, but not the second one ? More on stackoverflow.com
🌐 stackoverflow.com
March 13, 2016
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Errors › Invalid_array_length
RangeError: invalid array length - JavaScript - MDN Web Docs
August 21, 2026 - The JavaScript exception "Invalid array length" occurs when specifying an array length that is either negative, a floating number or exceeds the maximum supported by the platform (i.e., when creating an Array or ArrayBuffer, or when setting the length property).
Top answer
1 of 3
2

.length is a special property in Javascript arrays, which is defined as "the biggest numeric index in the array plus one" (or 2^32-1, whatever comes first). It's not "the number of elements", as the name might suggest.

When you iterate an array, either directly with for..of or map, or indirectly with e.g. JSON.stringify, JS just loops over all numbers from 0 to length - 1, and, if there's a property under this number, outputs/returns it. It doesn't look into other properties.

2 of 3
0

The length property don't work as one will expect on arrays that are hashtables or associative arrays. This property only works as one will expect on numeric indexed arrays (and normalized, i.e, without holes). But there exists a way for get the length of an associative array, first you have to get the list of keys from the associative array using Object.keys(arr) and then you can use the length property over this list (that is a normalized indexed array). Like on the next example:

arr=[];
arr[0]={"zero": "apple"};
arr[1]={"one": "orange"};
arr["fancy"]="what?";

console.log(Object.keys(arr).length);

And about this next question:

not able to get all values while doing console.log(JSON.stringify(arr))

Your arr element don't have the correct format to be a JSON. If you want it to be a JSON check the syntax on the next example:

jsonObj = {};
jsonObj[0] = {"zero": "apple"};
jsonObj[1] = {"one": "orange"};
jsonObj["fancy"] = "what?";

console.log(Object.keys(jsonObj).length);
console.log(JSON.stringify(jsonObj));

🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Array › length
Array: length - JavaScript - MDN Web Docs
The length data property of an Array instance represents the number of slots in that array. The value is an unsigned, 32-bit integer that is always numerically greater than the highest index in the array. It may be greater than the number of elements if the array is sparse.
🌐
Dustin John Pfister
dustinpfister.github.io › 2018 › 12 › 14 › js-array-length
Array length in javaScript and addressing the confusion | Dustin John Pfister at github pages
November 30, 2021 - In any case what I am driving at here is that arrays in javaScript are sparse in nature, and this sparse nature of javaScript arrays can result in problems and confusion if one is not aware of this, and how to go about dealing with it. One way of thinking about array length might be that Array length in javaScript refers to the highest numbered index value of an array plus one because array length is one rather than zero relative.
Top answer
1 of 3
97

One thing to note is that there is a difference between regular arrays and associative arrays. In regular arrays (real arrays), the index has to be an integer. On the other hand, associative arrays can use strings as an index. You can think of associative arrays as a map if you like. Now, also note, true arrays always start from zero. Thus in your example, you created an array in the following manner:

a = [];
a["1"] = {"string1":"string","string2":"string"};
a["2"] = {"string1":"string","string2":"string"}

Javascript was able to convert your string indexes into numbers, hence, your code above becomes:

a = [];
a[1] = {"blah"};
a[2] = {"blah"};

But remember what i said earlier: True arrays start from zero. Therefore, the javascript interpreter automatically assigned a[0] to the undefined. Try it out in either firebug or the chrome/safari console, and you will see something like this when you try to print "a". You should get something like "[undefined, Object, Object]. Hence the size 3 not 2 as you expected.

In your second example, i am pretty sure you are trying to simulate the use of an associated array, which essentially is adding properties to an object. Remember associated arrays enable you to use strings as a key. So in other terms, you are adding a property to the object. So in your example:

b["key1"] = {"string1":"string","string2":"string"};

this really means:

b.key1 = {"string1":"string","string2":"string"};

Initializing b =[] simply creates an array, but your assignment doesn't populate the array. It simply gives "b" extra properties.

2 of 3
19

length returns 1 + the largest integer key in the object.

In a the largest key is 2 so 1+2 is 3.

In b there are no integer keys (the keys there are key1 and key2 which cannot be converted into ints) so Javascript assumes that the largest key is -1, and 1 + -1 yields 0.

This program will help you see that:

a = [];
a["1"] = {};
a["4"] = {};
alert(a.length); // Prints 5
Find elsewhere
🌐
Dmitri Pavlutin
dmitripavlutin.com › the-magic-behind-array-length-property
The Magic Behind Array Length Property - Dmitri Pavlutin
January 17, 2016 - Being a collection, an important property to query is the number of items: Array.prototype.length. In JavaScript the length does not always indicate the number of existing elements (for sparse arrays) and modifying this property may remove elements.
Top answer
1 of 3
6

I'll convert my original comment to a more thorough answer.

Array indexes that are counted in .length go from 0 and up. Negative indexes are considered properties of the object, not array values. As you can see from the ECMAScript spec below, array indexes are essentially just certain types of property values given some special treatment.

From section 15.4 of the ECMAScript spec:

15.4 Array Objects

Array objects give special treatment to a certain class of property names. A property name P (in the form of a String value) is an array index if and only if ToString(ToUint32(P)) is equal to P and ToUint32(P) is not equal to 2^32. A property whose property name is an array index is also called an element. Every Array object has a length property whose value is always a nonnegative integer less than 2^32 . The value of the length property is numerically greater than the name of every property whose name is an array index; whenever a property of an Array object is created or changed, other properties are adjusted as necessary to maintain this invariant. Specifically, whenever a property is added whose name is an array index, the length property is changed, if necessary, to be one more than the numeric value of that array index; and whenever the length property is changed, every property whose name is an array index whose value is not smaller than the new length is automatically deleted. This constraint applies only to own properties of an Array object and is unaffected by length or array index properties that may be inherited from its prototypes.


Also, you should never "iterate" arrays with a for-in-loop:

for (var i in a1)

That iterates all enumerable properties of a1 which will include all array indexes, but could also include other properties. If you want to iterate only array elements with a for loop, you should use the other form:

for (var i = 0, len = a1.length; i < len; i++) 

It is slightly more typing, but a lot safer.

Or, in more modern browsers, you can use the .forEach() method.

2 of 3
1

It is because arrays in Javascript are zero-based, i.e. they start from zero and go up to length - 1.

You usually write your for loops to be bound by less-than operator like this:

for(i = 0; i < arr.length; i++) {
    // do something with arr[i]
}
Top answer
1 of 2
2

As stated here the length of an array must be less than 2 to the power of 32.

Your timestamps are larger than 2 to the power of 32, so cannot be array indices.

If you create an array a = [] and assign to a particular index a[33] = 'hi' then the previous 33 values will be undefined. But if the index you assign to is greater than 2**32 then the previous values will not be created, so the length of your array will be 0.

If you use a value over 2**32 as an index it will be treated as a property instead. So, if you want you can try iterating over the properties of the array.

I suggest that instead of combinedArray[value[0]], which will create properties, the following will get you an array you can iterate over:

var combinedArray = [];
var timestampIndices = [];

$.each(data.new, function(key, value) {
    combinedArray.push([value[0], value[1]]);
    timestampIndices.push(value[0]);
});

$.each(data.repeat, function(key, value) {
    let index = timestampIndices.indexOf(value[0]);
    combinedArray[index].push(value[1]);
});
2 of 2
2

The indices of your array are outside of the valid range of a positive 32 bit interger value.

From Array#length:

The length property of an object which is an instance of type Array sets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.

var array = [];
array[1541030400000] = 'foo';

console.log(array.length);
console.log(array);
console.log(array[1541030400000]);

To overcome this problem, you could take timestamps without milli seconds and take a smaller value as index for the array.

The array is then iterable with standard methods.

🌐
Medium
medium.com › @faheemkhan4865 › array-length-i-bet-youre-missing-something-961e7e70138e
Array.length: I bet, You’re missing something | by Faheemkhan | Medium
August 23, 2021 - But manually setting an index to a higher number creates empty slots in the array with undefined values. See the example below for more clarity. const arr = [10,20,30]; arr[5] = 60; const length = arr.length; console.log(length); // 6 console.log(arr) // [10, 20, 30, undefined, undefined, 60] Notice that elements in arr are undefined in middle.
🌐
freeCodeCamp
forum.freecodecamp.org › javascript
Arr.length not working correctly - JavaScript - The freeCodeCamp Forum
July 11, 2021 - Tell us what’s happening: Describe your issue in detail here. Sorry i’m a noob here, i just started coding few month ago from scratch. I can’t figure out why my code doesn’t show the real length of the array. I wold pass this challenge if only the length was the real one. function chunkArrayInGroups(arr, size) { let array = []; for (let i = 0; i
🌐
Kevin Chisholm
blog.kevinchisholm.com › javascript › javascript-array-length-always-one-higher
Why is a JavaScript array length property always one higher than the value of the last element's index? | Kevin Chisholm - Blog
February 10, 2021 - Home › JavaScript › Why is a JavaScript Array Length Property Always One Higher Than the Value of the Last Element’s Index? Arrays in JavaScript are zero-based. This means that JavaScript starts counting from zero when it indexes an array. In other words, the index value of the first element in the array is “0” and the index value of the second element is “1”, the third element’s index value is “2”, and so on. This is not ...