Skip to main content

countObjectKey

Counts only the own enumerable properties of an object, excluding inherited properties. Iterates through all enumerable properties using a for-in loop but filters to count only properties that belong directly to the object, not inherited from the prototype chain. This provides the same count as Object.keys().length but with better performance by avoiding array creation.

Signature

const countObjectKey: <Type extends object>(object: Type) => number

Parameters

NameTypeDescription
object-The object whose own properties to count

Returns

The count of own enumerable properties only

Examples

Basic usage with plain objects

import { countObjectKey } from '@winglet/common-utils';

// Plain object with own properties
const user = { name: 'Alice', age: 25, email: 'alice@example.com' };
console.log(countObjectKey(user)); // 3

// Empty object
console.log(countObjectKey({})); // 0

// Object with mixed key types
const mixed = {
str: 'value',
123: 'numeric',
[Symbol.for('sym')]: 'symbol' // Symbols are not counted
};
console.log(countObjectKey(mixed)); // 2 (symbols excluded)

Excluding inherited properties from prototype chain

// Object with inherited properties
const parent = { inherited1: 'value1', inherited2: 'value2' };
const child = Object.create(parent);
child.own1 = 'first';
child.own2 = 'second';

// countObjectKey counts only own properties
console.log(countObjectKey(child)); // 2

// Compare with countKey which includes inherited
import { countKey } from '@winglet/common-utils';
console.log(countKey(child)); // 4

// Same result as Object.keys().length
console.log(Object.keys(child).length); // 2

Working with constructor functions and prototypes

// Constructor with prototype methods
function Car(brand, model) {
this.brand = brand;
this.model = model;
}
Car.prototype.start = function() { console.log('Starting...'); };
Car.prototype.stop = function() { console.log('Stopping...'); };

const myCar = new Car('Toyota', 'Camry');
myCar.year = 2024;

// Only counts own properties, not prototype methods
console.log(countObjectKey(myCar)); // 3 (brand, model, year)
console.log(Object.keys(myCar)); // ['brand', 'model', 'year']

Performance optimization for large objects

// Large object with many properties
const largeData = {};
for (let i = 0; i < 100000; i++) {
largeData[`key_${i}`] = i;
}

// countObjectKey avoids array allocation
console.time('countObjectKey');
countObjectKey(largeData); // ~1ms
console.timeEnd('countObjectKey');

console.time('Object.keys.length');
Object.keys(largeData).length; // ~8ms (creates large array)
console.timeEnd('Object.keys.length');

// ~8x faster for large objects

Handling objects with null prototype

// Object without prototype chain
const nullProto = Object.create(null);
nullProto.prop1 = 'value1';
nullProto.prop2 = 'value2';
nullProto.prop3 = 'value3';

// Works correctly with null prototype objects
console.log(countObjectKey(nullProto)); // 3

// No Object.prototype methods available
console.log(nullProto.toString); // undefined
console.log(nullProto.hasOwnProperty); // undefined

Security-conscious property counting

// Potential prototype pollution scenario
const data = JSON.parse(untrustedInput);

// countObjectKey safely counts only own properties
const ownPropCount = countObjectKey(data);

// Safe validation
if (ownPropCount > MAX_ALLOWED_PROPERTIES) {
throw new Error('Too many properties');
}

// Process only own properties
for (const key in data) {
if (hasOwnProperty(data, key)) {
processProperty(key, data[key]);
}
}

Playground

import { countObjectKey } from '@winglet/common-utils';

// Plain object with own properties
const user = { name: 'Alice', age: 25, email: 'alice@example.com' };
console.log(countObjectKey(user)); // 3

// Empty object
console.log(countObjectKey({})); // 0

// Object with mixed key types
const mixed = {
str: 'value',
123: 'numeric',
[Symbol.for('sym')]: 'symbol' // Symbols are not counted
};
console.log(countObjectKey(mixed)); // 2 (symbols excluded)

Notes

Behavior Details:

  • Counts ONLY own enumerable properties
  • Uses hasOwnProperty check for each property
  • Excludes inherited properties from prototype chain
  • Excludes non-enumerable properties
  • Excludes symbol properties
  • Equivalent to Object.keys(obj).length in result

Performance Characteristics:

  • Time Complexity: O(n) where n is total enumerable properties
  • Space Complexity: O(1) constant space
  • ~3-8x faster than Object.keys().length (varies by object size)
  • No intermediate array allocation
  • Slightly slower than countKey due to hasOwnProperty checks

Use Cases:

  • Counting properties for validation or limits
  • Security-sensitive contexts (avoiding prototype pollution)
  • Performance-critical counting of own properties
  • Compatibility with Object.keys() behavior
  • Working with objects from untrusted sources

When to Use countKey Instead:

  • Need to include inherited properties intentionally
  • Working with objects designed to use prototype inheritance
  • Maximum performance when prototype checking not needed
  • Counting all enumerable properties is the goal

Implementation Note: Uses the hasOwnProperty utility which properly handles edge cases like objects with null prototype or overridden hasOwnProperty method.