That's because categoryData is not an Array - it's an Object. And while some JS objects (arguments, for example) support length property, those created with object literal notation do not.

You can count your object's length by yourself, with this:

function countProps(obj) {
    var count = 0;
    for (var p in obj) {
      obj.hasOwnProperty(p) && count++;
    }
    return count; 
}

This can be done even in a more simple way, if your target environment supports (or has it shimmed) the Object.keys method:

function sizeObj(obj) {
  return Object.keys(obj).length;
}

... and that's exactly how it's done in Underscore.js library method:

_.size = function(obj) {
    if (obj == null) return 0;
    return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
};
Answer from raina77ow on Stack Overflow
🌐
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 - When working with typed arrays the length property refers to the number of bit sized units the array is. For example if it is a Unit16Array and it has 3 elements the length of it is 3, and the byte length of it is 6. The length of an array generally refers to the number of elements, or the highest index value plus one. It does not always refer to the the size of the array in terms of data. So in javaScript there is the delete operator which can be used to delete object properties.
Discussions

Javascript Array length not working in safari
Find answers to Javascript Array length not working in safari from the expert community at Experts Exchange More on experts-exchange.com
🌐 experts-exchange.com
June 7, 2009
Arr.length not working correctly
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 ... More on forum.freecodecamp.org
🌐 forum.freecodecamp.org
4
0
July 11, 2021
.length not working
Tell us what’s happening: The .length on index is not working inside the loop. Is that normal? Your code so far function findLongestWordLength(str) { let theRegex = /\S+/g; let newStr = str.match(theRegex); console.log(newStr); let strLength=[]; for(let i =0; i More on forum.freecodecamp.org
🌐 forum.freecodecamp.org
16
0
July 9, 2020
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
🌐
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).
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Global_Objects › Array › length
Array: length - JavaScript - MDN Web Docs
Setting any array index (a nonnegative integer smaller than 232) beyond the current length extends the array — the length property is increased to reflect the new highest index. Setting length to an invalid value (e.g., a negative number or a non-integer) throws a RangeError exception.
🌐
Experts Exchange
experts-exchange.com › questions › 24470016 › Javascript-Array-length-not-working-in-safari.html
Solved: Javascript Array length not working in safari | Experts Exchange
June 7, 2009 - var aryItems = new Array(); function add2Array(theName){aryItems[aryItems.length] = theName;} function checkArray(theName){ for ( var z=0, len = aryItems.length; z < len; ++z ){ if (aryItems[z] == theName){ arrayFound = true; break; } } } ... We believe in human intelligence. Our moderation policy strictly prohibits the use of LLM content in our Q&A threads. ... You need to show the rest of the page This works fine in Safari on MAC - note I initialised arrayFound
🌐
JavaScript in Plain English
javascript.plainenglish.io › array-length-can-lead-to-unexpected-errors-ce4fbfa74fc5
Array. length Can Lead to Unexpected Errors | JavaScript in Plain English
July 8, 2022 - But what if I tell you that Array. length isn’t the best method to find the length of an array in JavaScript? But why? Is this because JavaScript is crazy or we don’t understand it well enough? Well, let’s see. In JavaScript, arrays are not primitives but are instead objects. This means that the array’s square bracket declaration probably works as a syntactical sugar to declare an array, but actually, behind the scenes, an object gets created with indexes (0-based) as keys and the array content as respective values.
🌐
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
🌐
freeCodeCamp
forum.freecodecamp.org › javascript
.length not working - JavaScript - The freeCodeCamp Forum
July 9, 2020 - Tell us what’s happening: The .length on index is not working inside the loop. Is that normal? Your code so far function findLongestWordLength(str) { let theRegex = /\S+/g; let newStr = str.match(theRegex); console.log(newStr); let strLength=[]; for(let i =0; i
Find elsewhere
🌐
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.
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));

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
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.

🌐
W3Schools
w3schools.com › jsref › jsref_length_array.asp
JavaScript Array length Property
The length property sets or returns the number of elements in an array.
🌐
Krasimirtsonev
krasimirtsonev.com › blog › article › unexpected-usage-of-array-length
Unexpected usage of Array.length
We added one item at the end of the array. It’s value is undefined. We may set length to ten and we'll get six more undefined elements. We are not actually adding a new element. We simply say that the value of length property ofarris 5.
Top answer
1 of 4
11

Quoting ECMA Script 5 Specification of Array Objects,

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 232−1.

Since Hello is not valid, according to the above definition, it is not considered as an array index but just as an ordinary property.

Quoting MDN's Relationship between length and numerical properties section,

When setting a property on a JavaScript array when the property is a valid array index and that index is outside the current bounds of the array, the engine will update the array's length property accordingly

So, only if the property is a valid array index, the length property will be adjusted.

In your case, you have just created a new property Hello on the array object.


Note: Only the numerical properties will be used in all of the Array's prototype functions, like forEach, map, etc.

For example, the array shown in question, when used with forEach,

arr.forEach(function(currentItem, index) {
    console.log(currentItem, index);
})

would print

Hello 0
There 1
123 2
456 3
{ show: [Function] } 4

even though the list of keys shows Hello.

console.log(Object.keys(arr));
// [ '0', '1', '2', '3', '4', 'Hello' ]

It is because, Array is derived from Object,

console.log(arr instanceof Object);
// true

and Hello is a valid key of the array object, but just not a valid array index. So, when you treat the array as an Object, Hello will be included in the keys, but the array specific functions will include only the numerical properties.

2 of 4
1

javascript length is calculated as 1+(highest numeric index element). so when you add arr['Hello'], you are only adding a string index which is not taken into account when calculating the array length.

This is the actual definition of the array length property as described in ECMAScript 5.1:

Every Array object has a length property whose value is always a nonnegative integer less than 232. 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.