Prima di tutto, non usare mai un for in
ciclo per enumerare un array. Mai. Usa il buon vecchio for(var i = 0; i<arr.length; i++)
.
Il motivo dietro questo è il seguente: ogni oggetto in JavaScript ha un campo speciale chiamato prototype
. Tutto ciò che aggiungi a quel campo sarà accessibile su ogni oggetto di quel tipo. Supponiamo che tu voglia che tutte le matrici abbiano una nuova fantastica funzione chiamata filter_0
che filtra gli zero.
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]
Questo è un modo standard per estendere oggetti e aggiungere nuovi metodi. Molte biblioteche lo fanno. Tuttavia, diamo un'occhiata a come for in
funziona ora:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
Vedi? Improvvisamente pensa che filter_0 sia un altro indice dell'array. Certo, non è in realtà un indice numerico, ma for in
enumera attraverso i campi oggetto, non solo gli indici numerici. Quindi ora stiamo enumerando tutti gli indici numerici e filter_0
. Ma filter_0
non è un campo di alcun oggetto array particolare, ogni oggetto array ha questa proprietà ora.
Fortunatamente, tutti gli oggetti hanno un hasOwnProperty
metodo, che controlla se questo campo appartiene davvero all'oggetto stesso o se è semplicemente ereditato dalla catena del prototipo e quindi appartiene a tutti gli oggetti di quel tipo.
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
Si noti che sebbene questo codice funzioni come previsto per gli array, non si dovrebbe mai, mai , usare for in
e for each in
per gli array. Ricorda che for in
enumera i campi di un oggetto, non gli indici o i valori dell'array.
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))
per limitare l'elaborazione solo alle proprietà proprie (non ereditate). Tuttavia, in alcuni casi si desidera veramente scorrere su tutte le proprietà, comprese quelle ereditate. In tal caso, JSLint ti obbliga a racchiudere il corpo del ciclo in un'istruzione if per decidere quali proprietà desideri veramente. Questo funzionerà e renderà felice JSlint:if (evtListeners[ind] !== undefined)