for..in
не циклически перебирает индексы массива, он перебирает перечисляемые имена свойств объекта . Бывает, что единственными перечислимыми экземплярами массива свойств по умолчанию являются индексы массива, и поэтому в большинстве случаев он работает, полагая, что он использует индексы массива в ограниченных ситуациях. Но это не то, что делает for..in
, и неправильное понимание этого будет кусать вас. :-) Он ломается, как только вы добавляете какие-либо дополнительные свойства в массив (совершенно допустимая вещь), или любая библиотека, которую вы используете, решает расширить прототип массива (также допустимая вещь).
В любом случае, то, что вы получаете от document.getElementsByTagName
, не является массивом . Это NodeList
. Лучшая ставка для итерации по NodeList
s - использовать явный индекс а-ля ответа Pointy - например, цикл прямого счета:
var i;
for (i = 0; i < list.length; ++i) {
// ... do your thing ...
}
Несколько не по теме, потому что это не относится к вашему NodeList
, но: когда вы на самом деле работаете с реальным массивом, поскольку массивы в JavaScript немногочисленны, для for..in
есть применимость, вам просто нужно четко понимать, что вы делаете (просматривая имена свойств, а не индексы). Возможно, вы захотите выполнить цикл только столько раз, сколько массива содержит фактические записи, чем циклически проходить по всем индексам в промежутках в разреженном массиве. Вот как вы это делаете:
var a, name;
a = [];
a[0] = "zero";
a[10000] = "ten thousand";
for (name in a) {
// Only process this property name if it's a property of the
// instance itself (not its prototype), and if the name survives
// transition to and from a string unchanged -- e.g., it's numeric
if (a.hasOwnProperty(name) && parseInt(name) == name) {
alert(a[name]);
}
}
Выше приведены только два предупреждения: «ноль» и «десять тысяч»; в то время как цикл прямого счета без проверок будет предупреждать 10 001 раз (в основном, говоря «не определено», потому что он проходит через пробел).