Reference

Reference · Objects

Object.keys()

Object.keys() returns an array of an object's own enumerable string keys — the standard way to count properties or iterate over an object by turning it into an array first.

XCODXReference · Updated

Definition

Object.keys() returns an array containing the names of an object's own enumerable string-keyed properties. It is the most common first step in working with an object as data: once you have the keys as an array, you can count them, iterate them, sort them, or map over them like any other array.

"Own" means it ignores properties inherited from the prototype chain, and "enumerable" means it skips the handful of properties explicitly hidden from enumeration. For the plain objects you build with {}, that's simply every key you put in — which is exactly what you want.

Because the result is an ordinary array, everything you know about arrays applies at once: .length counts the properties, .map() transforms the keys, .filter() selects some, .sort() orders them. That is the whole appeal of Object.keys() — it converts the things objects are awkward at (counting, iterating, transforming) into the things arrays are best at, in a single call, without you writing a loop by hand.

Syntax

Object.keys(obj)

// obj: the object whose own enumerable keys you want
// returns: a new array of strings

Parameters

ParameterRequiredDescription
objYesThe object to read keys from. A non-object argument is coerced to an object first (e.g. a string yields its index keys).

Object.keys() is a static method — you call it as Object.keys(obj), not obj.keys(). Its siblings Object.values(obj) and Object.entries(obj) follow the same shape, returning the values and the [key, value] pairs respectively.

Return value

A new array of the object's own enumerable keys, as strings. An object with no such properties returns an empty array. The original object is not modified.

  • Integer-like keys come first, in ascending numeric order; all other string keys follow in insertion order.
  • Symbol keys are never included (use Object.getOwnPropertySymbols for those).
  • Inherited (prototype) properties are excluded.

Examples

Count and list the keys

Iterate an object via its keys

const scores = { math: 90, art: 78 };

Object.keys(scores).forEach((key) => {
  console.log(`${key}: ${scores[key]}`);
});
// math: 90
// art: 78

Check whether an object is empty

const isEmpty = (obj) => Object.keys(obj).length === 0;

console.log(isEmpty({}));        // true
console.log(isEmpty({ a: 1 }));  // false

Transform keys with map

const prices = { pen: 3, book: 12 };

const labels = Object.keys(prices).map((k) => k.toUpperCase());
console.log(labels); // ['PEN', 'BOOK']

Sort the keys alphabetically

const obj = { banana: 1, apple: 2, cherry: 3 };

const sortedKeys = Object.keys(obj).sort();
console.log(sortedKeys); // ['apple', 'banana', 'cherry']

Browser & runtime support

Object.keys() vs for...in

Both visit an object's keys, but Object.keys() returns only the object's own enumerable keys as an array, while a for...in loop also walks inherited enumerable keys from the prototype chain. That inherited behavior is a classic source of bugs, which is why Object.keys() (or Object.entries()) is the safer, more predictable default — you get a clean array of exactly the object's own properties, and array methods to process it.

A related method, Object.getOwnPropertyNames(), returns non-enumerable own keys too, which Object.keys() deliberately skips. In everyday code you almost always want Object.keys(): the properties you set on a plain object literal are all enumerable, so it lines up with what JSON.stringify() serialises and with the own keys for...in would see. Reach for getOwnPropertyNames only when you are deliberately inspecting hidden, non-enumerable properties.

One performance note: each call allocates a fresh array, so avoid calling Object.keys() repeatedly on the same object inside a hot loop — capture it once in a variable and reuse it. For the object sizes you meet in ordinary application code the cost is negligible and clarity wins, but it is worth knowing when a loop runs millions of times.

Availability

Object.keys() has been standard since ECMAScript 5 (2009) and works in every modern browser and every maintained version of Node.js. The guaranteed key order (integers first, then insertion order) was formalised in ES2015 and is safe to rely on today.

Frequently asked questions

What order does Object.keys() return keys in?
Integer-like keys first in ascending numeric order, then all other string keys in the order they were inserted. This order has been guaranteed since ES2015.
Does Object.keys() include inherited properties?
No. It returns only the object's own enumerable string keys, ignoring anything inherited from the prototype chain — unlike a for...in loop.
How do I count the properties of an object?
Use Object.keys(obj).length, which gives the number of own enumerable properties.
Why is it Object.keys(obj) and not obj.keys()?
Object.keys is a static method on the Object constructor, so you pass the object as an argument. This avoids adding a keys method to every object you create.