How to efficiently count the number of keys/properties of an object in JavaScript

JavascriptPerformancePropertiesCountKey

Javascript Problem Overview


What's the fastest way to count the number of keys/properties of an object? Is it possible to do this without iterating over the object? I.e., without doing:

var count = 0;
for (k in myobj) if (myobj.hasOwnProperty(k)) ++count;

(Firefox did provide a magic __count__ property, but this was removed somewhere around version 4.)

Javascript Solutions


Solution 1 - Javascript

To do this in any ES5-compatible environment, such as Node.js, Chrome, Internet Explorer 9+, Firefox 4+, or Safari 5+:

Object.keys(obj).length

Solution 2 - Javascript

You could use this code:

if (!Object.keys) {
    Object.keys = function (obj) {
        var keys = [],
            k;
        for (k in obj) {
            if (Object.prototype.hasOwnProperty.call(obj, k)) {
                keys.push(k);
            }
        }
        return keys;
    };
}

Then you can use this in older browsers as well:

var len = Object.keys(obj).length;

Solution 3 - Javascript

If you are using Underscore.js you can use _.size (thanks douwe):

_.size(obj)

Alternatively you can also use _.keys which might be clearer for some:

_.keys(obj).length

I highly recommend Underscore.js. It's a tight library for doing lots of basic things. Whenever possible, they match ECMAScript 5 and defer to the native implementation.

Otherwise I support Avi Flax' answer. I edited it to add a link to the MDC documentation which includes the keys() method you can add to non-ECMAScript 5 browsers.

Solution 4 - Javascript

The standard Object implementation (ES5.1 Object Internal Properties and Methods) does not require an Object to track its number of keys/properties, so there should be no standard way to determine the size of an Object without explicitly or implicitly iterating over its keys.

So here are the most commonly used alternatives:

1. ECMAScript's Object.keys()

Object.keys(obj).length; Works by internally iterating over the keys to compute a temporary array and returns its length.

  • Pros - Readable and clean syntax. No library or custom code required except a shim if native support is unavailable
  • Cons - Memory overhead due to the creation of the array.
2. Library-based solutions

Many library-based examples elsewhere in this topic are useful idioms in the context of their library. From a performance viewpoint, however, there is nothing to gain compared to a perfect no-library code since all those library methods actually encapsulate either a for-loop or ES5 Object.keys (native or shimmed).

3. Optimizing a for-loop

The slowest part of such a for-loop is generally the .hasOwnProperty() call, because of the function call overhead. So when I just want the number of entries of a JSON object, I just skip the .hasOwnProperty() call if I know that no code did nor will extend Object.prototype.

Otherwise, your code could be very slightly optimized by making k local (var k) and by using prefix-increment operator (++count) instead of postfix.

var count = 0;
for (var k in myobj) if (myobj.hasOwnProperty(k)) ++count;

Another idea relies on caching the hasOwnProperty method:

var hasOwn = Object.prototype.hasOwnProperty;
var count = 0;
for (var k in myobj) if (hasOwn.call(myobj, k)) ++count;

Whether this is faster or not on a given environment is a question of benchmarking. Very limited performance gain can be expected anyway.

Solution 5 - Javascript

Here are some performance tests for three methods;

https://jsperf.com/get-the-number-of-keys-in-an-object

Object.keys().length

20,735 operations per second

It is very simple and compatible and runs fast but expensive, because it creates a new array of keys, which then gets thrown away.

return Object.keys(objectToRead).length;

Loop through the keys

15,734 operations per second

let size=0;
for(let k in objectToRead) {
  size++
}
return size;

It is slightly slower, but nowhere near the memory usage, so it is probably better if you're interested in optimising for mobile or other small machines.

Using Map instead of Object

953,839,338 operations per second

return mapToRead.size;

Basically, Map tracks its own size, so we're just returning a number field. It is far, far faster than any other method. If you have control of the object, convert them to maps instead.

Solution 6 - Javascript

If you are actually running into a performance problem I would suggest wrapping the calls that add/remove properties to/from the object with a function that also increments/decrements an appropriately named (size?) property.

You only need to calculate the initial number of properties once and move on from there. If there isn't an actual performance problem, don't bother. Just wrap that bit of code in a function getNumberOfProperties(object) and be done with it.

Solution 7 - Javascript

As answered in a previous answer: Object.keys(obj).length

But: as we have now a real Map class in ES6, I would suggest to use it instead of using the properties of an object.

const map = new Map();
map.set("key", "value");
map.size; // THE fastest way

Solution 8 - Javascript

As stated by Avi Flax,

Object.keys(obj).length

will do the trick for all enumerable properties on your object, but to also include the non-enumerable properties, you can instead use the Object.getOwnPropertyNames. Here's the difference:

var myObject = new Object();

Object.defineProperty(myObject, "nonEnumerableProp", {
  enumerable: false
});
Object.defineProperty(myObject, "enumerableProp", {
  enumerable: true
});

console.log(Object.getOwnPropertyNames(myObject).length); //outputs 2
console.log(Object.keys(myObject).length); //outputs 1

console.log(myObject.hasOwnProperty("nonEnumerableProp")); //outputs true
console.log(myObject.hasOwnProperty("enumerableProp")); //outputs true

console.log("nonEnumerableProp" in myObject); //outputs true
console.log("enumerableProp" in myObject); //outputs true

As stated here, this has the same browser support as Object.keys.

However, in most cases, you might not want to include the nonenumerables in these type of operations, but it's always good to know the difference ;)

Solution 9 - Javascript

To iterate on Avi Flax' answer, Object.keys(obj).length is correct for an object that doesn’t have functions tied to it.

Example:

obj = {"lol": "what", owo: "pfft"};
Object.keys(obj).length; // should be 2

versus

arr = [];
obj = {"lol": "what", owo: "pfft"};
obj.omg = function(){
    _.each(obj, function(a){
        arr.push(a);
    });
};
Object.keys(obj).length; // should be 3 because it looks like this
/* obj === {"lol": "what", owo: "pfft", omg: function(){_.each(obj, function(a){arr.push(a);});}} */

Steps to avoid this:

  1. do not put functions in an object that you want to count the number of keys in

  2. use a separate object or make a new object specifically for functions (if you want to count how many functions there are in the file using Object.keys(obj).length)

Also, yes, I used the _ or Underscore.js module from Node.js in my example.

Documentation can be found here as well as its source on GitHub and various other information.

And finally a lodash implementation https://lodash.com/docs#size

_.size(obj)

Solution 10 - Javascript

I'm not aware of any way to do this. However, to keep the iterations to a minimum, you could try checking for the existence of __count__ and if it doesn't exist (i.e., not Firefox) then you could iterate over the object and define it for later use, e.g.:

if (myobj.__count__ === undefined) {
  myobj.__count__ = ...
}

This way, any browser supporting __count__ would use that, and iterations would only be carried out for those which don't. If the count changes and you can't do this, you could always make it a function:

if (myobj.__count__ === undefined) {
  myobj.__count__ = function() { return ... }
  myobj.__count__.toString = function() { return this(); }
}

This way, any time you reference myobj.__count__ the function will fire and recalculate.

Solution 11 - Javascript

From Object.defineProperty():

> Object.defineProperty(obj, prop, descriptor)

You can either add it to all your objects:

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

Or a single object:

var myObj = {};
Object.defineProperty(myObj, "length", {
    enumerable: false,
    get: function() {
        return Object.keys(this).length;
    }
});

Example:

var myObj = {};
myObj.name  = "John Doe";
myObj.email = "[email protected]";
myObj.length; // Output: 2

Added that way, it won't be displayed in for..in loops:

for(var i in myObj) {
    console.log(i + ": " + myObj[i]);
}

Output:

name: John Doe
email: [email protected]

Note: it does not work in browsers before Internet Explorer 9.

Solution 12 - Javascript

For those who have Underscore.js included in their project you can do:

_({a:'', b:''}).size() // => 2

or functional style:

_.size({a:'', b:''}) // => 2

Solution 13 - Javascript

this works for both, Arrays and Objects

function count(obj){
    	return Object.keys(obj).length
     }

Solution 14 - Javascript

How I've solved this problem is to build my own implementation of a basic list which keeps a record of how many items are stored in the object. It’s very simple. Something like this:

function BasicList()
{
   var items = {};
   this.count = 0;

   this.add = function(index, item)
   {
      items[index] = item;
      this.count++;
   }

   this.remove = function (index)
   {
      delete items[index];
      this.count--;
   }

   this.get = function(index)
   {
      if (undefined === index)
        return items;
      else
        return items[index];
   }
}

Solution 15 - Javascript

For those that have Ext JS 4 in their project, you can do:

Ext.Object.getSize(myobj);

The advantage of this is that it'll work on all Ext JS compatible browsers (Internet Explorer 6 - Internet Explorer 8 included). However, I believe the running time is no better than O(n) though, as with other suggested solutions.

Solution 16 - Javascript

You can use:

Object.keys(objectName).length; 

and

Object.values(objectName).length;

Solution 17 - Javascript

The OP didn't specify if the object is a nodeList. If it is, then you can just use the length method on it directly. Example:

buttons = document.querySelectorAll('[id=button)) {
console.log('Found ' + buttons.length + ' on the screen');

Solution 18 - Javascript

If jQuery in previous answers does not work, then try

$(Object.Item).length

Solution 19 - Javascript

I don't think this is possible (at least not without using some internals). And I don't think you would gain much by optimizing this.

Solution 20 - Javascript

I try to make it available to all objects like this:

Object.defineProperty(Object.prototype,
                      "length",
                      {
                          get() {
                              if (!Object.keys) {
                                  Object.keys = function (obj) {
                                      var keys = [],k;
                                      for (k in obj) {
                                          if (Object.prototype.hasOwnProperty.call(obj, k)) {
                                              keys.push(k);
                                          }
                                      }
                                      return keys;
                                  };
                              }
                              return Object.keys(this).length;
                      },});

console.log({"Name":"Joe", "Age":26}.length) // Returns 2

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmjsView Question on Stackoverflow
Solution 1 - JavascriptAvi FlaxView Answer on Stackoverflow
Solution 2 - JavascriptRenaat De MuynckView Answer on Stackoverflow
Solution 3 - JavascriptstudgeekView Answer on Stackoverflow
Solution 4 - JavascriptLuc125View Answer on Stackoverflow
Solution 5 - JavascriptSteve CooperView Answer on Stackoverflow
Solution 6 - JavascriptConfusionView Answer on Stackoverflow
Solution 7 - JavascriptFlavien VolkenView Answer on Stackoverflow
Solution 8 - JavascriptBenderTheOffenderView Answer on Stackoverflow
Solution 9 - JavascriptBelldanduView Answer on Stackoverflow
Solution 10 - JavascriptLuke BennettView Answer on Stackoverflow
Solution 11 - JavascriptlepeView Answer on Stackoverflow
Solution 12 - JavascripthakuninView Answer on Stackoverflow
Solution 13 - JavascriptdazzafactView Answer on Stackoverflow
Solution 14 - JavascriptAliView Answer on Stackoverflow
Solution 15 - JavascriptMark RhodesView Answer on Stackoverflow
Solution 16 - JavascriptFayazView Answer on Stackoverflow
Solution 17 - JavascriptRobert SinclairView Answer on Stackoverflow
Solution 18 - JavascriptcodejoecodeView Answer on Stackoverflow
Solution 19 - JavascriptamixView Answer on Stackoverflow
Solution 20 - JavascriptTaquatechView Answer on Stackoverflow