What Is Enumerable?

What Is Enumerable?

if you’ve ever looped over an object in JavaScript and wondered why some properties don’t show up enumerable is your answer.
Let’s break it down.

What Is Enumerable?

Every property in a JavaScript object has hidden metadata called property descriptors. One of those descriptors is enumerable  a simple true or false flag that controls whether a property appears when you iterate over an object.

// Every property secretly looks like this:
{
  value: 42,
  writable: true,
  enumerable: true,   // 👈 this one
  configurable: true
}

What Does enumerable: true vs false Actually Do?
When enumerable is true, the property shows up in:

  • for...in loops
  • Object.keys()
  • Object.values()
  • Object.entries()
  • Spread operator { ...obj }

When enumerable is false, the property is hidden from all of those, but it’s not gone. You can still access it directly.

A Simple Example

const obj = {};

Object.defineProperty(obj, 'hidden', {
  value: 'secret',
  enumerable: false
});

Object.defineProperty(obj, 'visible', {
  value: 'hello',
  enumerable: true
});

console.log(Object.keys(obj));         // ['visible']
console.log(obj.hidden);               // 'secret' ← still accessible!
console.log(obj.visible);              // 'hello'

for (let key in obj) {
  console.log(key);                    // 'visible' only
}

Notice: hidden is not deleted, it just doesn’t show up in loops or key listings.

Normal Assignment = Enumerable by Default

const user = { name: 'Alice', age: 30 };

// Both properties are enumerable: true by default
console.log(Object.keys(user)); // ['name', 'age']

When you assign properties the normal way (using = or object literals), they’re enumerable by default.

How to Check Enumerability

const obj = { name: 'Alice' };

// Method 1: propertyIsEnumerable
console.log(obj.propertyIsEnumerable('name')); // true

// Method 2: getOwnPropertyDescriptor
const descriptor = Object.getOwnPropertyDescriptor(obj, 'name');
console.log(descriptor.enumerable); // true

Real-World Example: Prototype Methods
This is why Array.prototype.map doesn’t appear when you loop over an array:

const arr = [1, 2, 3];

for (let key in arr) {
  console.log(key); // '0', '1', '2' — NOT 'map', 'filter', etc.
}

// Those methods exist but are non-enumerable
const desc = Object.getOwnPropertyDescriptor(Array.prototype, 'map');
console.log(desc.enumerable); // false

If they were enumerable, every for...in loop over an array would expose all built-in methods — a mess you definitely don’t want.

Creating Non-Enumerable Properties

Use Object.defineProperty() to hide internal properties:


const person = { name: 'Bob' };

Object.defineProperty(person, '_id', {
  value: 'abc123',
  enumerable: false,   // hidden from loops
  writable: false,     // can't change
  configurable: false  // can't delete or redefine
});

console.log(Object.keys(person)); // ['name']
console.log(person._id);          // 'abc123'

This is a clean way to attach metadata to an object without polluting your data output.

Spread and Non-Enumerable Properties

const original = {};
Object.defineProperty(original, 'secret', {
  value: 'hidden',
  enumerable: false
});
original.name = 'Alice';

const copy = { ...original };

console.log(copy.name);   // 'Alice'
console.log(copy.secret); // undefined ← not copied!

Summary

  • enumerable: true, property appears in loops and key methods (default for normal assignments)
  • enumerable: false, property is hidden from loops but still accessible directly
  • Use Object.defineProperty() to control enumerability
  • Built-in prototype methods (mapfilter, etc.) are non-enumerable by design
  • Spread { ...obj } only copies enumerable own properties
Author: Danyal
I'm a skilled programmer specializing in Vue.js/Nuxt.js for front-end development and PHP Laravel for back-end solutions. I have a strong focus on API design and development, complemented by experience in web server setup and maintenance. My versatile expertise ensures seamless creation and maintenance of web applications, covering everything from intuitive user interfaces to robust server-side functionality. Passionate about coding and driven by a lifelong learning mindset, I invite you to explore more at danyal.dk.