Add a way of checking the actual number of items in an array

I was recently working on a project when I noticed that Array.prototype.length doesn't actually seem to be the length of the array. Rather it's the highest index in the array plus one. Looking into this some more, it seems like this is the intended behaviour, which strikes me as bizarre.

I suggest adding an new property to arrays: Array.prototype.size. Array.prototype.size would represent the actual number of items in the array, excluding empty spaces. The reason that i'm suggesting that this property be called size is because that is what's used in other constructs like Maps.
This may have already been suggested, and if so, I apologise.

Here's an example implementation:

Object.defineProperty(Array.prototype, "size", {
    get: function() {
        let counter = 0;
        this.forEach(() => counter++)
        return counter;
    }
})

And here are some examples of using it, run in Edge 98:

[].size // -> 0
[].length // -> 0

[1,2].size // -> 2
[1,2].length // -> 2

[1,,2].size // -> 2
[1,,2].length // -> 3

What are your thoughts on this?

Object.defineProperty(Array.prototype, "size", {
    get: function() {
        return Object.keys(this).length;
    }
})

do the same thing?

1 Like

From Array.from and sparse arrays

At the last TC39 meeting, we agreed holes are freakish and should be discounted in designing new APIs like Array.from (I think; I may be overstating slightly, but that's the effect).

I don't think the general sentiment has changed since then. Just don't use sparse arrays, you won't need .size then.

No, it won't do the same thing. That would also count non-index properties, and e.g. give the wrong size for Object.assign([], {example: "boom!"}).size.

A similarly simple implementation would be

 return this.filter(() => true).length;

but forEach is probably more efficient.

1 Like

More like Object.keys(this).filter(k => /^\d+$/.test(k)).length, but yes.

There's no easy way to count array elements from Object.keys. "007" and "123456789012" are both valid object keys that can be set on the array, but are not elements.

A bit surprising nobody said arr.reduce(n=>n+1, 0) ;)

2 Likes

I agree that holes in arrays are a terrible thing that should never have existed, but I still think that this is an important feature. I know that I've had several headaches that would have been avoided if there was a simple way to check the actual number of items in an array natively in the language, and I'm sure that lots of other people feel the same.
At the moment I have to import a helper function every time I want to count the number of items in an array (so that I don't need to modify the prototype), which seems like something that just shouldn't need to be done.

1 Like

Newer EcmaScript APIs Often treat arrays with holes, and arrays filled with undefined as the same thing. For example:

> [...[2,,3].values()] // An array with a whole
[ 2, undefined, 3 ]
> [...[2,undefined,3].values()] // An array with undefined
[ 2, undefined, 3 ]

If others follow suit and also design their APIs to treat holes like undefined, then I don't think there's a reason to know the number of non-hole elements in an array, as a "hole" should ideally be indistinguishable from an undefined entry from the API's perspective.

But, perhaps, would you be able to elaborate on one of your use cases? So we can have a better idea of why this would be valuable?

1 Like

Exactly this. The proper number of items in an array to think about, sparse or otherwise, is the length. Just pretend holes don’t exist.