0

Why does the length property of an Array not get iterated over in a for in loop? I have the following code:

var a = new Array();
for (i in a) { 
    if (i === 'length') 
        alert(i) 
};

The above doesn't result in any alert. However, if I change the 'length' string to 'clone', an alert is raised. I don't understand this, since both 'length' and 'clone' seem to be members of the Array object, as can be seen by:

console.dir(a)

Searching Google, I only found the suggestion to use the hasOwnProperty method. This doesn't help, and only results in no alert being raised for either case.

Inder Kumar Rathore
  • 39,458
  • 17
  • 135
  • 184
Roy
  • 35
  • 4
  • https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#Enumerable_attribute – zerkms May 03 '15 at 08:18

1 Answers1

5

The for (i in a) structure in Javascript lists the properties of a Javascript object that are marked as enumerable. It lists all enumerable properties of the object whether they are directly on the object or inherited via the prototype. 'enumerable` is a specific characteristic of a property. You can have properties of an object that are enumerable or not enumerable.

The .length property is not marked as enumerable so it does not show using the for (i in a) structure. If you create a property yourself with Object.defineProperty(), you can control the enumerable attribute (along with several other attributes). If you just add a property directly without specifying its custom attributes using Object.defineProperty(), then the property will be enumerable by default.

For a variety of reasons, you should never attempt to iterate the elements of an Array with the for (i in a) structure. That structure is explicitly designed to list out the enumerable properties of a Javascript object which will include all Array elements, but may also include other enumerable properties too (as you've seen). Array elements should be enumerated with:

for (var i = 0, len = array.length; i < len; i++) {
    // array[i]
}

or

array.forEach(function(val, index, array) {
    // code here
});

As for your observation about .clone, that is not a standard property of an Array object. I'm guessing that it may have been added to the Array prototype by some third party library and it is apparently marked as enumerable which explains why it shows in your for (i in a) loop.


.hasOwnProperty() is often used to filter out properties that are on the prototype so you only iterate properties which are applied directly to the object (not inherited from a prototype) which explains why it would filter out the .clone property (if it was on the prototype).

In any case, if your objective is to iterate the elements of an array (and not any custom properties added to the Array object), then you should use one of the above two methods of iteration and then you won't have to worry about .hasOwnProperty() or other enumerable properties on the prototype or on the Array object itself.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Thanks for the quick reply. I tried checking: `a.propertyIsEnumerable('clone')` and `a.propertyIsEnumerable('length')` but both returned false. If what you explained above is true, then shouldn't 'clone' not be iterated over either? – Roy May 03 '15 at 08:34
  • @Roy - you'd have to show us the specific code you're using and how the `clone` property is getting there for us to see exactly what's going on in your case. If you can recreate that in a jsFiddle, we could take look at it. Per [this description on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/propertyIsEnumerable) `.propertyIsEnumerable()` will match up with `for (i in a)` only if the property is NOT on the prototype so that's probably why you see a divergence. – jfriend00 May 03 '15 at 08:39
  • Never mind, something changed and now no alert is being raised for any property of Array. ```var a = new Array(); for (i in a) { alert(i) }; ``` Anyway, the link provided by zerkms confirms that your answer is correct. Thanks for the help. – Roy May 03 '15 at 08:43