Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript: Unenumerable properties - when and why?

I have recently stumbled upon the issue of using for..in loops on arrays in JavaScript.

According to the answers in this question, for..in is intended to enumerate the properties of an object, including inherited ones.

If so, why do we have the ability to define properties as non-enumerable using Object.defineProperty? Doesn't this goes against the whole intention of for..in? Or is it considered as bad practice and should be avoided?

Also, why would we want to iterate over all the properties in such a manner in the first place (i.e. using a for..in loop)? When could this come in handy?

And why not define all (Array) prototype extensions as non-enumerable and keep using for..in with arrays?

like image 203
Johan Hirsch Avatar asked Aug 17 '15 13:08

Johan Hirsch


People also ask

What is non-enumerable property in JavaScript?

Objects can have properties that don't show up when iterated through the particular object using Object. keys() or for...in loop. Those type of properties are called as non-enumerable properties.

What is the purpose of enumerable attribute when we define a new property in object?

The enumerable property attribute defines whether the property is picked by Object.

What is enumerable properties in JavaScript?

Enumerable properties are those properties whose internal enumerable flag is set to true, which is the default for properties created via simple assignment or via a property initializer. Properties defined via Object. defineProperty and such are not enumerable by default.

Does order of properties in JavaScript matter?

YES (but not always insertion order). Most Browsers iterate object properties as: Positive integer keys in ascending order (and strings like "1" that parse as ints) String keys, in insertion order (ES2015 guarantees this and all browsers comply)


1 Answers

The problem is that there's only one namespace for object properties (ignoring the Symbol feature in ES2015 for now). There are some object properties that you do want to be enumerable, and some you don't. The properties that contain object data and relationships to other objects share that namespace with the names of methods.

The for ... in loop looks not only at the properties of the object directly involved, but also up the prototype chain. That's probably the most likely use for non-enumerable properties: the methods that you may want to put on a prototype object probably don't need to be enumerable.

To me the real reason not to use for ... in when you're iterating through the numeric-name properties of an Array instance is that there's no guarantee you'll iterate through the indexes in any particular order. Though most runtime systems do give back numeric-name properties in the obvious order, the specification for the language absolutely does not require that that be the case. By using an explicit numeric index in a plain for loop, you thereby explicitly control the iteration order.

People who write JavaScript code for use in contexts where there'll be other code running over which they have no control (think advertising-supported sites, or sites with lots of metrics tools) know that relying on built-in prototypes not to be polluted with random junk is deeply unwise. Using for ... in puts your code at the mercy of the worst coder contributing to that third-party code.

Modern implementations have Object.keys(), which returns the enumerable "own" property names of an object; that is, the names of properties directly on the object, and none from the prototype chain.

like image 193
Pointy Avatar answered Sep 21 '22 20:09

Pointy