153

Is there a way to get (from somewhere) the number of elements in a Javascript object?? (i.e. constant-time complexity).

I can't find a property or method that retrieves that information. So far I can only think of doing an iteration through the whole collection, but that's linear time.
It's strange there is no direct access to the size of the object, don't you think.

EDIT:
I'm talking about the Object object (not objects in general):

var obj = new Object ;
1

7 Answers 7

195

Although JS implementations might keep track of such a value internally, there's no standard way to get it.

In the past, Mozilla's Javascript variant exposed the non-standard __count__, but it has been removed with version 1.8.5.

For cross-browser scripting you're stuck with explicitly iterating over the properties and checking hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

In case of ECMAScript 5 capable implementations, this can also be written as (Kudos to Avi Flax)

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

Keep in mind that you'll also miss properties which aren't enumerable (eg an array's length).

If you're using a framework like jQuery, Prototype, Mootools, $whatever-the-newest-hype, check if they come with their own collections API, which might be a better solution to your problem than using native JS objects.

Sign up to request clarification or add additional context in comments.

6 Comments

Goddamn it I always forget hasOwnProperty. Too much time in .NET land I tell you. +1
jQuery uses an object for its collections that it gets from queries, and it exposes that value with a length property.
Firefox4 __count__ is gone :(
Is there a way to do this without a for in? I'm in the same type of bind but I'd like to make it pass JSLint if at all possible.
why do we need hasOwnProperty() ?
|
157

To do this in any ES5-compatible environment

Object.keys(obj).length

(Browser support from here)
(Doc on Object.keys here, includes method you can add to non-ECMA5 browsers)

3 Comments

This is not the right question to put this answer on. With that you are taking all the keys of the object, putting them in a newly created array and then retrieving the length property from that new array.
It may not be the most programmatically efficient, but it is the most developer efficient.
I agree, it´s definately the fastest (short, quickly done) way to do this. Works well with nested objects too, if you are only interested in the sub-object´s own keys, Object.keys(obj.nested_obj).length.
10

if you are already using jQuery in your build just do this:

$(yourObject).length

It works nicely for me on objects, and I already had jQuery as a dependancy.

3 Comments

Strange... this doesn't work for me. I always get 1. ZelkiN's answer works for me.
This code always return 1. Just 1 object. It is not counting elements in it
Did one of the up voters check the code? It doesn't work and returns always 1 - regardless what yourObject contains.
7
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);

Comments

1

AFAIK, there is no way to do this reliably, unless you switch to an array. Which honestly, doesn't seem strange - it's seems pretty straight forward to me that arrays are countable, and objects aren't.

Probably the closest you'll get is something like this

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

But this creates problems, or at least questions. All user-created properties are counted, including the _length function itself! And while in this simple example you could avoid it by just using a normal function, that doesn't mean you can stop other scripts from doing this. so what do you do? Ignore function properties?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

In the end, I think you should probably ditch the idea of making your objects countable and figure out another way to do whatever it is you're doing.

3 Comments

DANGER WILL ROBINSON! Do NOT proto against Object! Everything descends from Object, you'll cripple the client processing like this if you're doing any sizeable amount of JS work.
Uh... did you not read the part where I wrote in a comment "Monkey patching on purpose to make a point" - c'mon, I did that deliberately so that people wouldn't flip a bit about it. Besides, even though I don't advocate monkey patching, you misunderstand how the prototype chain works in Javascript if you think this would cause performance issues video.yahoo.com/watch/111585/1027823
So.. this is a do or a don't?
0

The concept of number/length/dimensionality doesn't really make sense for an Object, and needing it suggests you really want an Array to me.

Edit: Pointed out to me that you want an O(1) for this. To the best of my knowledge no such way exists I'm afraid.

3 Comments

He proposed iterating himself, which this solution is. He needed an O(1) way to achieve this...
You're quite right. Really should read questions more thoroughly.
Actually, Objects are the closest thing to a Map there is in JS. Maps do have length.
0

With jquery :

$(parent)[0].childElementCount

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.