Primeiro de tudo, nunca use um for in
loop para enumerar sobre uma matriz. Nunca. Use bom e velho for(var i = 0; i<arr.length; i++)
.
A razão por trás disso é o seguinte: cada objeto em JavaScript tem um campo especial chamado prototype
. Tudo o que você adicionar a esse campo estará acessível em todos os objetos desse tipo. Suponha que você deseje que todas as matrizes tenham uma nova função interessante chamada filter_0
que filtrará os zeros.
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]
Essa é uma maneira padrão de estender objetos e adicionar novos métodos. Muitas bibliotecas fazem isso. No entanto, vamos ver como for in
funciona agora:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
Você vê? De repente, pensa que filter_0 é outro índice de matriz. Obviamente, não é realmente um índice numérico, mas for in
enumera através de campos de objetos, não apenas índices numéricos. Então, agora estamos enumerando todos os índices numéricos e filter_0
. Mas filter_0
não é um campo de nenhum objeto de matriz específico, todo objeto de matriz possui essa propriedade agora.
Felizmente, todos os objetos têm um hasOwnProperty
método que verifica se esse campo realmente pertence ao próprio objeto ou se é simplesmente herdado da cadeia de protótipos e, portanto, pertence a todos os objetos desse tipo.
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
Note que embora este código funciona como esperado para arrays, você não deve nunca, nunca mais , o uso for in
e for each in
para arrays. Lembre-se de que for in
enumera os campos de um objeto, não os índices ou valores da 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 o processamento apenas às propriedades (não herdadas). Ainda assim, em alguns casos, você realmente deseja iterar sobre todas as propriedades, incluindo as herdadas. Nesse caso, o JSLint obriga a envolver o corpo do loop em uma instrução if para decidir quais propriedades você realmente deseja. Isto irá funcionar e fazer JSLint feliz:if (evtListeners[ind] !== undefined)