Почему "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)
Ответ 2
Скорость?
Цикл for(..;..;..)
оказался в 36 раз быстрее, чем for .. in
когда я тестировал его здесь.
Ссылка любезно предоставлена этим SO
Ответ 3
Если вы используете для /in, то item
перечисляет через строковые значения "0", "1",..., а не фактические объекты в списке. Таким образом, "элемент" в первом фрагменте больше похож на i
во втором фрагменте, а не на item
. Кроме того, строковые значения перечисляются там, где вы ожидаете числа. И у вас возникают проблемы, когда вы добавляете свойства в список, например array.ID = "a123"
, поскольку они также будут перечислены.
Но с этими недостатками я все еще думаю, что синтаксис очень полезен, если ваша команда знает, что он делает.
Ответ 4
Добавьте list.foo = bar;
и попробуйте использовать простой for
.
Если вы не используете некоторые библиотеки (например, prototypeJs) и не добавляете никаких новых свойств в объект массива, вы можете использовать простой for-statement.