Back to JavaScript
2026-04-227 min read

Enumerability and ownership of properties (JavaScript)

Learn Enumerability and ownership of properties (JavaScript) step by step with clear examples and exercises.

Why This Matters

Understanding enumerability and ownership of properties is crucial for mastering JavaScript. This knowledge empowers developers to navigate complex objects, debug issues, optimize performance, and work effectively with third-party libraries or frameworks.

Prerequisites

To fully grasp the concepts presented in this lesson, you should have a strong foundation in:

  1. Basic JavaScript syntax
  2. Objects and properties in JavaScript
  3. Looping constructs (for...in, for, and for-of)
  4. ES6 features like let, const, arrow functions, and destructuring
  5. Familiarity with the prototype chain and inheritance
  6. Understanding of closures and scopes in JavaScript
  7. Knowledge of common built-in methods related to objects (e.g., Object.keys, Object.values, Object.entries)

Core Concept

Every property in a JavaScript object can be classified by three factors: enumerable or non-enumerable, string or symbol, and own or inherited from the prototype chain.

Enumerability

Properties with the internal enumerable flag set to true are considered enumerable. By default, properties created via simple assignment or property initializers have this flag set to true. However, properties defined using Object.defineProperty and similar methods are non-enumerable by default. Most iteration means (such as for...in loops and Object.keys) only visit enumerable keys.

Enumerability Example

const myObj = {
prop1: 'enum', // Enumerable property created via simple assignment
prop2: undefined, // Non-enumerable property created using Object.defineProperty
};

Object.defineProperty(myObj, 'prop2', {
enumerable: false,
value: 'nonEnum'
});

console.log(Object.keys(myObj)); // Output: ['prop1']

In the example above, prop1 is enumerable and will be included in the output of Object.keys, while prop2 is non-enumerable and will not be included.

Ownership

Ownership of a property determines whether it belongs directly to the object or is inherited from its prototype chain. All properties, enumerable or not, string or symbol, own or inherited, can be accessed with dot notation (obj.property) or bracket notation (obj['property']).

Ownership Example

const myObj = Object.create({
prop0: 'prototype' // Inherited property from the prototype object
});
myObj.prop1 = 'own'; // Own property added to the object

console.log(myObj.prop0); // Output: 'prototype'
console.log(myObj.hasOwnProperty('prop0')); // Output: false (since prop0 is inherited)

In this example, prop0 is inherited from the prototype object and considered non-own, while prop1 is an own property added to the object.

Worked Example

Let's create a simple object with both enumerable and non-enumerable properties, then demonstrate how to iterate through them using for...in and Object.keys.

const myObj = {
enumProp: 'enum', // Enumerable property created via simple assignment
nonEnumProp: undefined, // Non-enumerable property created using Object.defineProperty
};

Object.defineProperty(myObj, 'nonEnumProp', {
enumerable: false,
value: 'nonEnum'
});

// Iterating with for...in loop
for (const key in myObj) {
console.log(`Key: ${key}, Value: ${myObj[key]}`);
}

// Iterating with Object.keys
console.log(Object.keys(myObj));

Output:

Key: enumProp, Value: enum
Key: nonEnumProp, Value: nonEnum
['enumProp']

In this example, the for...in loop iterates over both enumerable and non-enumerable properties, while Object.keys only returns enumerable properties.

Common Mistakes

  1. Assuming all properties are enumerable by default: Remember that non-enumerable properties will not be included in iteration methods like for...in and Object.keys unless explicitly set to enumerable.
  1. Not understanding the difference between own and inherited properties: While both can be accessed using dot or bracket notation, they have different implications when it comes to object traversal and inheritance.
  1. Forgetting to set the enumerable flag when defining properties with Object.defineProperty: If you want a property to be enumerable, make sure to set the enumerable flag to true.
  1. Confusing enumerability with accessibility: Enumerability only affects whether a property is included in iteration methods; it does not affect whether the property can be accessed directly or through getters/setters.
  1. Ignoring the role of prototypes and inheritance: Understanding how properties flow through the prototype chain is essential for understanding enumerability and ownership.
  1. Not considering Symbols as property keys: While we will focus on string properties in this lesson, it's important to remember that symbols can also be used as unique property keys.

Practice Questions

  1. Create an object with both enumerable and non-enumerable properties. Iterate through them using for...in and Object.keys.
  2. Given an object, write a function that returns all properties (both enumerable and non-enumerable) as an array.
  3. Explain the difference between own and inherited properties in JavaScript objects.
  4. If you have an object with only non-enumerable properties, what will be the output when iterating over it using for...in or Object.keys?
  5. How can you make all properties of an object non-enumerable?
  6. How do you check if a property is enumerable or non-enumerable in JavaScript?
  7. What happens when you try to access a non-own property (i.e., one inherited from the prototype chain) using bracket notation on an object?
  8. Discuss the use of Symbols as property keys and their benefits over string keys.
  9. How can you create a getter/setter for a property in JavaScript, and how does it affect enumerability and ownership?
  10. What is the purpose of Object.getOwnPropertyDescriptors() method and how does it differ from Object.keys(), Object.values(), and Object.entries()?

FAQ

  1. Can I make all properties of an object non-enumerable?

Yes, you can set all properties to non-enumerable by iterating through each property using a for...in loop and defining them as non-enumerable using Object.defineProperty. However, this may not be practical in most cases.

  1. How do I check if a property is enumerable or non-enumerable?

You can use the Object.getOwnPropertyDescriptor method to get the descriptor of a property and then check its enumerable flag.

  1. What happens when I try to iterate over an object with only non-enumerable properties using for...in or Object.keys?

Iteration methods like for...in and Object.keys will not include non-enumerable properties in their output, so you won't see them when iterating over the object.

  1. How can I access a non-own property (i.e., one inherited from the prototype chain) using bracket notation on an object?

You cannot directly access non-own properties using bracket notation; instead, use dot notation or call the getter function if one is defined.

  1. What are some common uses for non-enumerable properties in JavaScript?

Non-enumerable properties can be used to store private data within an object, prevent accidental modification of critical properties, and optimize performance by avoiding unnecessary iterations during certain operations.

  1. How can I access a non-own property (i.e., one inherited from the prototype chain) using bracket notation on an object?

You cannot directly access non-own properties using bracket notation; instead, use dot notation or call the getter function if one is defined.

  1. What are Symbols and why are they useful as property keys in JavaScript?

Symbols are a unique type of data introduced in ES6 that can be used as property keys to create truly unique properties. This helps prevent naming collisions when dealing with third-party libraries or when multiple developers work on the same codebase. Symbols also do not appear in for...in and Object.keys iterations by default, making them useful for creating private properties.

  1. How can I create a getter/setter for a property in JavaScript?

You can define a getter and setter using the Object.defineProperty method with the get and set attributes. For example:

const myObj = {};

Object.defineProperty(myObj, 'myProp', {
get: function() {
return this._myProp;
},
set: function(value) {
this._myProp = value;
}
});
  1. What is the purpose of Object.getOwnPropertyDescriptors() method and how does it differ from Object.keys(), Object.values(), and Object.entries()?

The Object.getOwnPropertyDescriptors() method returns an object containing all own property descriptors (both enumerable and non-enumerable) for the specified object. It differs from Object.keys(), Object.values(), and Object.entries() in that it provides more detailed information about each property, including its writable, enumerable, and configurable flags, as well as getters and setters (if present).

  1. What happens when you try to access a non-existent property on an object?

Accessing a non-existent property on an object will result in undefined if the property is not enumerable or inherited from the prototype chain. If the property is enumerable but does not exist, it will be included in the output of iteration methods like for...in and Object.keys. To handle this case gracefully, you can use a try-catch block or the hasOwnProperty() method to check if a property exists before accessing it.

Enumerability and ownership of properties (JavaScript) | JavaScript | XQA Learn