Don't use for..in
for Array iteration.
It's important to understand that Javascript Array's square bracket syntax ([]
) for accessing indicies is actually inherited from the Object
...
obj.prop === obj['prop'] // true
The for..in
structure does not work like a more traditional for..each/in
that would be found in other languages (php, python, etc...).
Javascript's for..in
is designed to iterate over the properties of an object. Producing the key of each property. Using this key combined with the Object
's bracket syntax, you can easily access the values you are after.
var obj = {
foo: "bar",
fizz: "buzz",
moo: "muck"
};
for ( var prop in obj ) {
console.log(prop); // foo / fizz / moo
console.log(obj[prop]); // bar / buzz / muck
}
And because the Array is simply an Object with sequential numeric property names (indexes) the for..in
works in a similar way, producing the numeric indicies just as it produces the property names above.
An important characteristic of the for..in
structure is that it continues to search for enumerable properties up the prototype chain. It will also iterate inherited enumerable properties. It is up to you to verify that the current property exists directly on the local object and not the prototype it is attached to with hasOwnProperty()
...
for ( var prop in obj ) {
if ( obj.hasOwnProperty(prop) ) {
// prop is actually obj's property (not inherited)
}
}
(More on Prototypal Inheritance)
The problem with using the for..in
structure on the Array type is that there is no garauntee as to what order the properties are produced... and generally speaking that is a farily important feature in processing an array.
Another problem is that it usually slower than a standard for
implementation.
Bottom Line
Using a for...in
to iterate arrays is like using the butt of a screw driver to drive a nail... why wouldn't you just use a hammer (for
)?
Look at what's happening differently in each iteration:
for( var i = 0; i < p1.length; i++ )
- Check if
i < p1.length
- Increment
i
by one
Very simple and fast.
Now look at what's happening in each iteration for this:
for( var i in p1 )
Repeat
- Let P be the name of the next property of obj whose [[Enumerable]] attribute is true. If there is no such property, return (normal, V,
empty).
It has to find next property in the object that is enumerable. With your array you know that this can be achieved by a simple integer increment, where as the algorithm to find next enumerable is most likely not that simple because it has to work on arbitrary object and its prototype chain keys.
Best Answer
There is a slight difference between looping though the
Object.keys
array and looping using afor...in
statement, which in the majority of cases would not be noted.Object.keys(obj)
returns only an array with the own properties of the object, while thefor...in
returns also the keys found in the prototype chain, in order the latter to be done extra check to the prototype of theobj
is needed and then to the prototype of the prototype and so on and so forth, until the whole prototype chain has been visited. This certainly makes the second approach less efficient than the first, but as I have already mentioned, this difference would be hardly noticed in the majority of cases.For a more formal approach, as it is stated in the MDN: