Перш за все, ніколи не використовуйте for inцикл для перерахунку через масив. Ніколи. Використовуйте добрий старийfor(var i = 0; i<arr.length; i++) .
Причина цього полягає в наступному: кожен об’єкт у JavaScript має спеціальне поле під назвою prototype. Все, що ви додасте до цього поля, стане доступним для кожного об'єкта цього типу. Припустимо, ви хочете, щоб усі масиви мали класну нову функцію, яка називається, filter_0яка буде фільтрувати нулі.
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]
Це стандартний спосіб розширення об'єктів та додавання нових методів. Багато бібліотек роблять це. Однак давайте розглянемо, як for inпрацює зараз:
var listeners = ["a", "b", "c"];
for (o in listeners) {
console.log(o);
}
//prints:
// 0
// 1
// 2
// filter_0
Ви бачите? Раптом здається, що filter_0 - це ще один індекс масиву. Звичайно, це насправді не числовий індекс, але for inперераховується через об’єктні поля, а не просто числові індекси. Отже ми зараз перераховуємо кожен числовий індекс і filter_0 . Алеfilter_0 це не поле якогось конкретного об’єкта масиву, кожен об'єкт масиву має це властивість зараз.
На щастя, у всіх об'єктів є hasOwnPropertyметод, який перевіряє, чи справді це поле належить самому об'єкту, чи він просто успадковується від ланцюга прототипу і таким чином належить до всіх об'єктів цього типу.
for (o in listeners) {
if (listeners.hasOwnProperty(o)) {
console.log(o);
}
}
//prints:
// 0
// 1
// 2
Зауважте, що хоча цей код працює, як очікувалося, для масивів, ви ніколи, ніколи , не використовуйте for inта for each inдля масивів. Пам’ятайте, що for inперераховуються поля об’єкта, а не індекси чи значення масиву.
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))щоб обмежити обробку лише власними (не успадкованими) властивостями. Однак у деяких випадках ви дійсно хочете повторити всі властивості, включаючи успадковані. У такому випадку JSLint змушує вас обернути тіло циклу в операторі if, щоб вирішити, які властивості ви дійсно хочете. Це спрацює і зробить JSlint щасливим:if (evtListeners[ind] !== undefined)