En primer lugar, nunca use un for in
bucle para enumerar sobre una matriz. Nunca. Usa lo bueno de siempre for(var i = 0; i<arr.length; i++)
.
La razón detrás de esto es la siguiente: cada objeto en JavaScript tiene un campo especial llamado prototype
. Todo lo que agregue a ese campo será accesible en cada objeto de ese tipo. Suponga que desea que todas las matrices tengan una nueva función genial llamada filter_0
que filtre los ceros.
Array.prototype.filter_0 = function() {
var res = [];
for (var i = 0; i < this.length; i++) {
if (this[i] != 0) {
res.push(this[i]);
}
}
return res;
};
console.log([0, 5, 0, 3, 0, 1, 0].filter_0());
//prints [5,3,1]
Esta es una forma estándar de extender objetos y agregar nuevos métodos. Muchas bibliotecas hacen esto. Sin embargo, veamos cómo for in
funciona ahora:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
¿Lo ves? De repente piensa que filter_0 es otro índice de matriz. Por supuesto, no es realmente un índice numérico, sino que se for in
enumera a través de campos de objeto, no solo índices numéricos. Así que ahora estamos enumerando a través de cada índice numérico y filter_0
. Pero filter_0
no es un campo de ningún objeto de matriz en particular, cada objeto de matriz tiene esta propiedad ahora.
Afortunadamente, todos los objetos tienen un hasOwnProperty
método que comprueba si este campo realmente pertenece al objeto en sí o si simplemente se hereda de la cadena de prototipos y, por lo tanto, pertenece a todos los objetos de ese tipo.
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
Tenga en cuenta que, aunque este código funciona como se espera para las matrices, nunca, nunca , debe usar for in
y for each in
para las matrices. Recuerde que for in
enumera los campos de un objeto, no los índices o valores de la matriz.
var listeners = ["a", "b", "c"];
listeners.happy = "Happy debugging";
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
// happy
if (evtListeners.hasOwnProperty(ind))
para restringir el procesamiento solo a las propiedades propias (no heredadas). Aún así, en algunos casos realmente desea iterar sobre todas las propiedades, incluidas las heredadas. En ese caso, JSLint lo obliga a ajustar el cuerpo del bucle en una declaración if para decidir qué propiedades realmente desea. Esto funcionará y hará feliz a JSlint:if (evtListeners[ind] !== undefined)