Similar alternative: for..in
In Javascript there is a version of for
that has some similarities with the foreach
PHP. It is the closest type of construction, but it exists to iterate on object properties and not necessarily vector indices. Also, it is not possible to get the key and value automatically.
The syntax is:
for (<índice> in <vetor/objeto>)
Example:
var array = [1, 2, 3, 4];
for (index in array) {
var value = array[index];
console.log("array[" + index + "] = " + value);
}
Functional example in jsfiddle.
Iterating on object properties
As I mentioned, this kind of loop is not directed exactly to arrays, being mainly useful to iterate on the properties of any object:
Example:
var object = { nome: 'Luiz', idade: 29};
for (property in object) {
var value = object[property];
console.log("object[" + property + "] = " + value);
}
Functional example in jsfiddle.
A common application is to simulate a map or data dictionary. Another example is a sparse vector (which does not contain all indices sequentially from 0
to n
.
Attention to possible problems
As mentioned in other responses and comments, the loop for...in
may result in unwanted side effects.
For example, if a library defines one or more functions in the prototype
of the object. These functions will be included in the for..in
and it would be necessary to use the function hasOwnProperty
to ignore these "inherited functions".
Moreover, it is not guaranteed that numerical indexes will be traversed in some order.
Tip: avoid touching the prototype
From my point of view, tampering with prototype
of common objects should be avoided at all costs, as well as libraries that make such use.
For example, imagine that we will use an object as a map, dynamically assigning and retrieving attributes from it. As I walk through the keys to this map, at all times use the function hasOwnProperty
.
The question is: should we really have to worry that someone injected some "strange" element into our objects? I believe that.
In practice...
Although the for..in
always be accused of causing problems, in my experience I have never had difficulties in using it so much in arrays how much in objects normal, without the hasOwnProperty
. Probably this is due to the fact that I never allow "strange" code injecting "magic" functions without my knowledge.
Moreover, although the order of the elements is not guaranteed by the specification, I have also never witnessed in any browser indexes being traversed out of order, at least in arrays for real.
See the example below:
var array = new Array();
array.push("A");
array.push("B");
array.push("C");
delete array[1]
array[1] = 2;
for (i in array) {
console.log(i)
}
Even deleting a middle index of the array and then redefining it, the result will be 0
, 1
and 2
, in this order. See the jsfiddle. If anyone discovers a browser that behaves differently, please let me know.
On the other hand, if not use a array for real the result is different. See the example below:
var array = { }
array[0] = "A";
array[2] = "B";
array[1] = "C";
for (i in array) {
console.log(i)
}
See the jsfiddle.
Surprisingly, the result in Chrome is 0
, 1
and 2
. However, in Firefox and IE is 0
, 2
and 1
. Anyway, unless you use an object as a sparse vector, that is, adding larger elements before the smaller ones, there would be no problem in using the for..in
.
Anyway, the same care for using the for..in
in arrays serves for any object, so recommendations like "don’t use it" simply don’t make sense. Even if the prototype
is changed as long as I always use the hasOwnProperty()
and do not mind the order of the elements, there is no problem in using this type of loop.
Final considerations
Generally speaking, it’s really best to avoid the for..in
and opt for the for
traditional. Reasons:
- You may need a library to change the
prototype
. It is common to hear reports from people who add a certain Javascript library and it "breaks" its implementation.
- It also prevents other developers from misusing
prototype
and break the general system code.
Allows objects to simulate a array, defining the property length
and numeric attributes. This is very useful for generic routines that receive vectors. See the example below:
var array = {
0: "Primeiro",
1: "Segundo",
2: "Terceiro",
length: 3
};
for (var i = 0; i < array.length; i++) {
console.log('array[' + i + '] = ' + array[i]);
}
See the jsfiddle.
Congratulations on the answer! Very didactic and enlightening. (y)
– ed1nh0