Lodash _.keys() method

Beginner
⏱️ 6 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.keys(object) returns an array of own enumerable string-keyed property names.
  • What gets excluded: inherited, non-enumerable, and symbol-keyed properties.
  • How arrays, strings, null, and undefined behave.
  • When to use _.keysIn(), Object.keys(), or Reflect.ownKeys() instead.

Prerequisites

You should know the difference between own and inherited properties, and between enumerable and non-enumerable properties.

  • Own only: prototype properties are ignored. Use _.keysIn if you need inherited keys.
  • Enumerable only: properties defined with enumerable: false do not appear.
  • String keys only: symbol keys require Object.getOwnPropertySymbols or Reflect.ownKeys.

Overview

_.keys is Lodash’s object-name enumerator for the common case: own, enumerable, string-keyed properties. It is close to Object.keys, but it handles null and undefined more gently by returning an empty array. For objects with prototypes, symbols, or non-enumerable metadata, choose the narrower or broader native API intentionally.

Own enumerable names

The same mental model as forOwn and most DTO-building helpers.

Null-safe

_.keys(null) and _.keys(undefined) return [] instead of throwing.

Not a deep helper

It returns only first-level property names. It does not walk nested objects.

Syntax

javascript
_.keys(object)
  • object: value to inspect. Objects, arrays, strings, and array-like values are supported.
  • Returns: an array of own enumerable string-keyed property names.
1

Get own enumerable keys

For plain objects, _.keys returns the same useful surface you normally want to iterate or validate.

javascript
import keys from "lodash/keys";

const user = {
  name: "John",
  age: 30,
  email: "john@example.com"
};

keys(user);
// -> ["name", "age", "email"]

keys(user).forEach((key) => {
  console.log(key + ": " + user[key]);
});
// name: John
// age: 30
// email: john@example.com
Try it Yourself
2

Arrays, strings, null and undefined

Array indexes and string character positions are keys too. Lodash also avoids the Object.keys(null) throw by returning an empty array.

javascript
import keys from "lodash/keys";

keys(["a", "b", "c"]);
// -> ["0", "1", "2"]

const sparse = [];
sparse[2] = "two";
keys(sparse);
// -> ["0", "1", "2"]
//    Lodash iterates 0..length-1 for array-likes, so holes are reported.
//    Object.keys(sparse) returns only ["2"] for the same array.

keys("hi");
// -> ["0", "1"]

keys(null);
// -> []

keys(undefined);
// -> []
Try it Yourself
3

Inherited, non-enumerable and symbol keys

_.keys is deliberately narrow. If a property is inherited, non-enumerable, or symbol-keyed, it will not appear.

javascript
import keys from "lodash/keys";
import keysIn from "lodash/keysIn";

const hidden = Symbol("hidden");
const proto = { inherited: true };
const obj = Object.create(proto);

obj.visible = 1;
obj[hidden] = 2;
Object.defineProperty(obj, "secret", {
  value: 3,
  enumerable: false
});

keys(obj);
// -> ["visible"]

keysIn(obj);
// -> ["visible", "inherited"]

Object.getOwnPropertyNames(obj);
// -> ["visible", "secret"]

Reflect.ownKeys(obj);
// -> ["visible", "secret", Symbol(hidden)]
Try it Yourself

📋 _.keys vs related APIs

Topic_.keys_.keysInObject.keysReflect.ownKeys
Own string keysYesYesYesYes
Inherited string keysNoYesNoNo
Non-enumerable keysNoNoNoYes
Symbol keysNoNoNoYes
null / undefined[][]ThrowsThrows

Use _.keys for DTO-style own enumerable names, _.keysIn when inherited enumerable keys are part of the public shape, and Reflect.ownKeys when symbols or non-enumerable metadata matter.

Pitfalls to avoid

Inherited

Prototype keys are excluded

This is usually what you want. If your object intentionally exposes enumerable prototype properties, use _.keysIn.

Symbols

Symbols are not returned

_.keys returns names, not symbols. Use Reflect.ownKeys or Object.getOwnPropertySymbols for symbol-aware code.

Order

Sort when order matters

Property order is predictable by spec, but business logic should not depend on incoming object order. Sort the returned array if order is meaningful.

Strings

Strings produce character index keys

The old reference suggested invalid values return empty arrays, but _.keys("hi") returns ["0", "1"].

Sparse

Sparse arrays differ from Object.keys

Lodash treats array-likes as a 0..length-1 index range, so holes are returned. Object.keys reports only assigned indexes. Pick the helper that matches your data model.

❓ FAQ

An array of own enumerable string-keyed property names. It ignores inherited properties, non-enumerable properties, and symbol-keyed properties.
_.keys reports only own enumerable string keys. _.keysIn also includes inherited enumerable string keys from the prototype chain.
For ordinary objects and arrays they are very similar. Lodash is more forgiving for null and undefined, returning an empty array instead of throwing.
Yes. For arrays and array-like values, Lodash iterates 0..length-1 and returns every index as a string. Unlike Object.keys(), holes in sparse arrays are reported (so [,,'two'] returns ['0', '1', '2']).
No. It returns string-keyed property names only. Use Object.getOwnPropertySymbols or Reflect.ownKeys when symbol keys matter.
It follows JavaScript property enumeration order: integer-like keys first in ascending order, then other string keys in insertion order. Do not use key order as a business rule unless you sort explicitly.

Summary

Did you know?

_.keys returns only own enumerable string-keyed property names. It ignores inherited properties, non-enumerable properties, and symbol-keyed properties.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful