Any ideas why this is?
Because that's how the language works.
From MDN:
The length property represents an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.
From the spec:
Specifically, whenever an own property is added whose name is an array index, the value of the length property is changed, if necessary, to be one more than the numeric value of that array index;
Notice that it is not true that the length is always one greater than the index of the last populated item. In your case, if you did
answers[71] = {field: 'value'};
answers[31] = {field: 'value'};
The length would now be 72, but if you then did
delete answers[71];
the length would remain 72, and not be adjusted down to 32.
If your question was actually to find the actual number of populated slots in the array, see the other answers, or you could brute-force it, looping over all indexes up to the length and checking if a slot is populated using the in operator:
let count = 0;
for (let i = 0; i < arr.length; i++) count += i in arr;
71which creates array of length72and remaining elements would be undefinedanswers.filter(function(v){return true;}).length;, filter wouldn't itertate over undefined or deleted elementsvar answers = {};) instead of an array?