What does enumerable mean?
Asked Answered
P

8

176

I was directed to MDN's for..in page when it said, "for..in Iterates over the enumerable properties of an object."

Then I went to the Enumerability and ownership of properties page where it said "Enumerable properties are those which can be iterated by a for..in loop."

The dictionary defines enumerable as countable, but I can't really visualize what that means. Could i get an example of something being enumerable?

Poem answered 27/7, 2013 at 2:38 Comment(3)
Do you understand what for-in does?Iridescent
From the answers i got that for..in allows all enumerable properties of an object to be available for use with the for statementPoem
The simplest meaning is: whether a property will be produced by a for in loop or not (for those who don't want to know the details or just don't care ;))Kolnick
S
183

An enumerable property is one that can be included in and visited during for..in loops (or a similar iteration of properties, like Object.keys()).

If a property isn't identified as enumerable, the loop will ignore that it's within the object.

var obj = { key: 'val' };

console.log('toString' in obj); // true
console.log(typeof obj.toString); // "function"

for (var key in obj)
    console.log(key); // "key"

A property is identified as enumerable or not by its own [[Enumerable]] attribute. You can view this as part of the property's descriptor:

var descriptor = Object.getOwnPropertyDescriptor({ bar: 1 }, 'bar');

console.log(descriptor.enumerable); // true
console.log(descriptor.value);      // 1

console.log(descriptor);
// { value: 1, writable: true, enumerable: true, configurable: true }

A for..in loop then iterates through the object's property names.

var foo = { bar: 1, baz: 2};

for (var prop in foo)
    console.log(prop); // outputs 'bar' and 'baz'

But, only evaluates its statement – console.log(prop); in this case – for those properties whose [[Enumerable]] attribute is true.

This condition is in place because objects have many more properties, especially from inheritance:

console.log(Object.getOwnPropertyNames(Object.prototype));
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", /* etc. */]

Each of these properties still exists on the object:

console.log('constructor' in foo); // true
console.log('toString' in foo);    // true
// etc.

But, they're skipped by the for..in loop because they aren't enumerable.

var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor');

console.log(descriptor.enumerable); // false
Supplant answered 27/7, 2013 at 2:47 Comment(4)
So the constructor property is non-enumerable because it does not show up in the for..in loop. While the the names of the properties such as bar or baz are enumerable because you were able to console.log each one from the object?Poem
This is not entirely correct: But, they are skipped (or not counted) by the for..in loop because they are not enumerable. The properties on Object.prototype are in fact ignored because they are further up the prototype chain, not because they are not enumerable. Neither getOwnPropertyNames() or keys() show properties that are not an object's own. As a side note, it is true that many of the built-in properties are not enumerable and thus will not show with keys(), but you will have to write extra code if you want to traverse the prototype chain.Bekah
literally, enumerable means countableStickler
@Bekah They're using for..in, not keys(). for..in does walk the prototype chain, so being non-enumerable is the only thing keeping the built-in properties out.Burck
L
55

If you create an object via myObj = {foo: 'bar'} or something thereabouts, all properties are enumerable. So the easier question to ask is, what's not enumerable? Certain objects have some non-enumerable properties, for example if you call Object.getOwnPropertyNames([]) (which returns an array of all properties, enumerable or not, on []), it will return ['length'], which includes the non-enumerable property of an array, 'length'.

You can make your own non-enumerable properties by calling Object.defineProperty:

var person = { age: 18 };
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false });

person.name; // 'Joshua'
for (prop in person) {
  console.log(prop);
}; // 'age'

This example borrows heavily from Non-enumerable properties in JavaScript, but shows an object being enumerated over. Properties can either be or not be writable, configurable, or enumerable. John Resig discusses this in the scope of ECMAScript 5 Objects and Properties.

And, there's a Stack Overflow question about why you'd ever want to make properties non-enumerable.

Latrinalatrine answered 27/7, 2013 at 2:59 Comment(4)
Hm, both upvotes and downvotes. Certainly, if there's anything about this answer that's worth downvoting, please add a comment here.Latrinalatrine
Another answer wrote this: var o = {}; o['foo'] = 0; // enumerable, normal Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird Why explicitly add enumerable: false?Poem
@Patrick, I included it here in part so that it's clear from the example that it's an option, but depending on your audience, being explicit can be a solid decision just so that it's clear to anyone who's reading your code.Latrinalatrine
@Latrinalatrine Thanks for this short and very clear explanation, I couldn't get accepted answer until I went through yours :DRhearheba
D
44

It's a lot more boring than something that should be visualized.

There is literally an attribute on all properties called "enumerable." When it is set to false the for..in method will skip that property, pretend it doesn't exist.

There are a lot of properties on objects that have "enumerable" set to false, like "valueOf" and "hasOwnProperty," because it's presumed you don't want the JavaScript engine iterating over those.

You can create your own non-enumerable properties using the Object.defineProperty method:

  var car = {
    make: 'Honda',
    model: 'Civic',
    year: '2008',
    condition: 'bad',
    mileage: 36000
  };

  Object.defineProperty(car, 'mySecretAboutTheCar', {
    value: 'cat pee in back seat',
    enumerable: false
  });

Now, the fact that there is even a secret about the car is hidden. Of course they can still access the property directly and get the answer:

console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat'

But, they would have to know that the property exists first, because if they're trying to access it through for..in or Object.keys it will remain completely secret:

console.log(Object.keys(car)); //prints ['make', 'model', 'year', 'condition', 'mileage']

They should have just called it, "forInAble."

Dunc answered 19/11, 2015 at 7:21 Comment(6)
Upvoted for that last line - I think if it actually had been called forInAble no one would be asking about it at all. Which brings up my question - why would you (or why would you have to) set a property to not be enumerable? The length property of an array is used quite often as an example of a non-enumerable property, but why couldn't you just set it to enumerable (not the JavaScript restriction, I mean, why was it set to not enumerable in JavaScript in the first place)?Wilhite
To clarify my question, why was it decided that the following wasn't an option: make: Honda model: Civic secret: Cat pee length: 12Wilhite
Hmmm...I may have found the answer to my own question. From a google search for "What do you mean by enumerated data types?" Enumerated data has a finite set of values. An enumerated data type consists of values that you allow for that type, or enumerated values. For integer-based enumerated types, each enumerated value consists of a name and an underlying numeric value.So, if I understand correctly, since there are an infinite number of possible lengths, you would have to assign an infinite number of names, one name to each length. Is that correct?Wilhite
Well, addressing your first question, setting a non-enumerable property on an object is a little hacky, since the only way you'd be able to find out what was on that object would be to look at the code and as a code base develops it could be buried. So, generally, you wouldn't want to use it. Regarding '.length' which gives the number of characters in a string or elements in an array is just something that's presumed we wouldn't want included if we were using 'for... in.' Can't answer why the gods of Js made it that way necessarily. They have reasons (ahem) opinions beyond our comprehension.Dunc
...and I don't think I could answer your second question about enumerated data types, though it looks like something I could chew on for quite awhile if I had the time. :-)Dunc
Great answer, it's a skill to simplify something that is simple :)Perilous
R
10

If you're having difficulty visualising "what does it mean to be enumerable?" why not ask yourself, what does it mean to be nonenumerable?

I think of it a bit like this, a nonenumerable property exists but is partially hidden; meaning that nonenumerable is the weird one. Now you can imagine enumerable as what is left - the more natural property we're used to encountering since we discovered Objects. Consider

var o = {};
o['foo'] =  0;                               // enumerable, normal
Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird

Now in a for..in, imagine it like pseudocode

for property in o:
    if not property enumerable continue // skip non-enumerable, "bar"
    else do /* whatever */              // act upon enumerable, "foo"

where the body of the loop you typed in JavaScript is in the place of /* whatever */

Rochdale answered 27/7, 2013 at 3:1 Comment(0)
W
10

I will write one line definition of ENUMERABLE

Enumerable: Specifies whether the property can be returned in a for/in loop.

var obj = {};
Object.defineProperties(obj, {
    set1: {enumerable: true},
    set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]
Whiffen answered 2/8, 2016 at 13:26 Comment(0)
D
3

Built-in methods that objects inherit are not enumerable, but the properties that your code adds to objects are enumerable unless explicitly stated

Dactylology answered 26/11, 2019 at 15:11 Comment(0)
S
1

Think of the enum data type, just a structure of objects that correspond to different numbers. To declare something to as an enumerable is to declare that it corresponds to a specific number, allowing it to be given a place in a Dictionary that represents countable components of an object. To put it simply, making an object enumerable is the same as telling the compiler, "Hey, this property counts, I want to see this when I check for data on this object."

Soursop answered 1/11, 2019 at 12:14 Comment(0)
A
0

methods are not enumerable; or rather built in methods are not.. tho after searching on what enumerable means to java script; it just refers to a property attribute.. all created objects in ecma3 are enumerable, and ecma5 u can now define it....that's it.. :D lol took me a bit to find the answer; but I believe its talked about in David Flanagan's book.. so I guess it means "hidden", or not "hidden" in that methods are not shown in the for in loop, and thus are "hidden"

Audient answered 4/12, 2015 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.