![]()
Understanding Object.keys() Not Returning Prototype Properties in JavaScript
JavaScript provides several ways to retrieve an object’s properties, and one commonly used method is Object.keys(). However, many developers get confused when Object.keys() does not return properties inherited from the prototype chain. In this detailed explanation, we will cover:
- What
Object.keys()Does - Why Prototype Properties Are Not Included
- How to Retrieve Prototype Properties
- Alternatives to
Object.keys() - Best Practices
1. What Object.keys() Does
Object.keys(obj) returns an array of an object’s own enumerable properties (i.e., properties directly defined on the object and not inherited from the prototype chain).
Example:
const person = {
name: "Alice",
age: 30
};
console.log(Object.keys(person));
// Output: ["name", "age"]
2. Why Prototype Properties Are Not Included
Understanding Prototype Inheritance
JavaScript objects inherit properties from their prototype. However, Object.keys() only retrieves the object’s own properties and ignores prototype properties.
Example with a Prototype Property:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.greet = function() {
return "Hello!";
};
const alice = new Person("Alice", 30);
console.log(Object.keys(alice));
// Output: ["name", "age"] (prototype properties are NOT included)
console.log(alice.greet());
// Output: "Hello!" (Prototype method works fine)
Even though greet() exists on alice, it does not appear in Object.keys(alice) because it is an inherited property, not an own property.
3. How to Retrieve Prototype Properties
To get both own properties and inherited properties, use for...in instead of Object.keys().
Using for...in to Include Prototype Properties
for (let key in alice) {
console.log(key);
}
Output:
name
age
greet
The for...in loop iterates over all enumerable properties, including inherited ones.
However, to filter out prototype properties, you can use hasOwnProperty():
for (let key in alice) {
if (alice.hasOwnProperty(key)) {
console.log(key);
}
}
Output:
name
age
Now, only own properties are printed.
4. Alternatives to Object.keys()
If you need to retrieve all properties, including non-enumerable ones, consider:
1. Object.getOwnPropertyNames()
Retrieves all own properties, including non-enumerable properties.
console.log(Object.getOwnPropertyNames(alice));
// Output: ["name", "age"]
2. Object.getPrototypeOf()
Retrieves the object’s prototype, allowing access to inherited properties.
console.log(Object.getPrototypeOf(alice));
// Output: { greet: [Function] }
To get prototype properties, combine with Object.keys():
console.log(Object.keys(Object.getPrototypeOf(alice)));
// Output: ["greet"]
3. Reflect.ownKeys()
Retrieves both enumerable and non-enumerable properties, including Symbol keys.
console.log(Reflect.ownKeys(alice));
// Output: ["name", "age"]
5. Best Practices
- Use
Object.keys(obj)when you only need an object’s own enumerable properties. - Use
for...inwhen you need both own and inherited properties but filter withhasOwnProperty(). - Use
Object.getOwnPropertyNames(obj)if you also want non-enumerable properties. - Use
Object.getPrototypeOf(obj)to examine prototype properties. - Avoid modifying the prototype of built-in objects (
Array.prototype,Object.prototype) as it can lead to unexpected behaviors.
