Почему "for (var item in list)" с массивами считается плохой практикой в ​​JavaScript?

Для простого массива с нулевым индексом:

var list = ['Foo', 'Bar', 'Baz'];

Много раз я заметил, что когда кто-то предлагает перебирать переменные в массиве вроде этого:

for(var item in list) { ... }

... почти наверняка кто-то предлагает эту плохую практику и предлагает альтернативный подход:

var count = list.length;

for(var i = 0; i < count; i++) {
    var item = list[i];
    ...
}

В чем причина отказа от использования более простой версии выше и вместо этого использовать второй пример?

Ответ 1

Сначала порядок цикла undefined для цикла for...in, поэтому нет гарантии, что свойства будут итерированы в том порядке, в котором вы хотите.

Во-вторых, for...in выполняет итерацию по всем перечислимым свойствам объекта, включая те, которые унаследованы от его прототипа. В случае массивов это может повлиять на вас, если ваш код или любая библиотека, включенная в вашу страницу, расширила прототип Array, что может быть действительно полезной задачей:

Array.prototype.remove = function(val) {
    // Irrelevant implementation details
};

var a = ["a", "b", "c"];

for (var i in a) {
    console.log(i);
}

// Logs 0, 1, 2, "remove" (though not necessarily in that order)

Ответ 3

Если вы используете для /in, то item перечисляет через строковые значения "0", "1",..., а не фактические объекты в списке. Таким образом, "элемент" в первом фрагменте больше похож на i во втором фрагменте, а не на item. Кроме того, строковые значения перечисляются там, где вы ожидаете числа. И у вас возникают проблемы, когда вы добавляете свойства в список, например array.ID = "a123", поскольку они также будут перечислены.

Но с этими недостатками я все еще думаю, что синтаксис очень полезен, если ваша команда знает, что он делает.

Ответ 4

Добавьте list.foo = bar; и попробуйте использовать простой for. Если вы не используете некоторые библиотеки (например, prototypeJs) и не добавляете никаких новых свойств в объект массива, вы можете использовать простой for-statement.