Почему не стоит использовать цикл ‘for in’ в JavaScript?

Причина — в его поведении. Вот как работает обычный цикл ‘for’:

var a = [];
a[5] = 5; // Полностью верный Javascript-код, который создаёт массив
for (var i=0; i<a.length; i++) {
// Перебирает все целочисленные индексы массива от 0 до 5, как и ожидается
}

А теперь о том, как поведёт себя цикл ‘for in’ в этом случае:

var a = [];
a[5] = 5;
for (x in a) {
// Цикл выполнится только один раз для 5
// и проигнорирует индексы 0-4
}

Также учтите, что библиотеки Javascript (типа MooTools) часто делают подобные вещи, которые будут иметь отношение ко всем массивам, которые Вы создаёте:

// Где-то глубоко в какой-нибудь Javascript-библиотеке:
Array.prototype.foo = 1;
// Попробуйте угадайте, что сделает следующий код:
var a = [''a'',''b'',''c'',''d'',''e''];
for (var x in a){
// Сейчас ‘foo’ является частью ЛЮБОГО массива
// и отобразится здесь как значение переменной ‘x’
console.log(x); // Выводит 0, 1, 2, 3, 4, foo (!!!)
}

Для избежания этой проблемы можно поступить следующим образом:

for (var x in a) {
// Отсеиваем здесь свойства не принадлежащие ‘a’
if (a.hasOwnProperty(x)) {
console.log(x); // Получим 0, 1, 3, 3, 4
}
}

Некоторые даже рекомендуют вызывать этот метод прямо из Object.prototype, чтобы избежать проблем в том случае, если кто-то добавит свойство с именем hasOwnProperty к Вашему объекту, хотя это и маловероятно.

for (var x in a) {
if (Object.prototype.hasOwnProperty.call(a, x)) {
console.log(x); // Получим 0, 1, 3, 3, 4
}
}

Также поведение этого цикла может быть непредсказуемым в старых браузерах, таких как IE 8 и ниже:

var array = [];
array[2] = ''c'';
array[1] = ''b'';
array[0] = ''a'';
for (var p in array) {
// В этом месте ‘p’ будет 2, 1 а затем 0 (в IE8 и ниже)
}

При использовании цикла ‘for in’ всегда используйте ключевое слово var перед значением ключа, так Вы обезопасите себя от переназначения соответствующей переменной, если она встречается в глобальном контексте.

Вывод: использовать этот цикл можно, просто надо делать это с осторожностью.

По вопросам рекламы [email protected]