Javascript forin, кажется, возвращает только каждый второй индекс в массиве

У меня есть страница (на самом деле, около тридцати или около того), где я пытаюсь изменить имя класса определенных элементов на основе переменной строки запроса. Все работает нормально, кроме этой части, я получаю действительно странный результат...

        var hitAreas = document.getElementsByClassName('hitArea');
    alert(hitAreas.length);
    for(hitArea in hitAreas)
    {
        alert(hitAreas[hitArea]);
        hitAreas[hitArea].className = 'hitArea_practice';
    }

Предупреждение (hitAreas.length); строка правильно возвращает количество элементов (7, из приведенного ниже html) с именем класса «hitArea», но когда я перебираю hitAreas, он только меняет имена классов для каждого другого элемента на странице. На полпути он возвращает undefined в качестве значения для alert(hitAreas[hitArea]); предположительно, потому что он пытается ссылаться на элементы массива за пределами индекса 6.

Тело html-страницы:

        <body onload="toggleHotspotHints();">
<div>
    <img src="Dashboard1.jpg" width="1440" height="795" />
    <div class="hitArea" style="top: 55px; left: 230px; width: 72px; height: 17px;" onclick="gotoPage('BatchReconcile/1-ClaimsReconcileMenu');"></div>
    <div class="hitArea" style="top: 55px; left: 319px; width: 72px; height: 17px;" onclick="gotoPage('Eligibility/PP Elig 1');"></div>
    <div class="hitArea" style="top: 55px; left: 409px; width: 72px; height: 17px;" onclick="gotoPage('REPORTS/5-Dashboard Reports List');"></div>
    <div class="hitArea" style="top: 137px; left: 260px; width: 145px; height: 21px;" onclick="gotoPage('Dash2_Messages');"></div>
    <div class="hitArea" style="top: 223px; left: 247px; width: 126px; height: 19px;" onclick="gotoPage('ClaimsList_Failed');"></div>
    <div class="hitArea" style="top: 242px; left: 247px; width: 126px; height: 14px;" onclick="gotoPage('PayerReportList');"></div>
    <div class="hitArea" style="top: 258px; left: 247px; width: 126px; height: 14px;" onclick="gotoPage('ADM/1_trending graph');"></div>
</div>

Live demo: http://jsfiddle.net/simevidas/LE6UN/


person Eric    schedule 03.03.2011    source источник


Ответы (1)


Шиме Видас указал, что getElementsByClassName повторно настраивает живой список узлов, что означает, что сохраненная коллекция будет обновляться по мере изменения (здесь атрибут class).

var hitAreas = document.getElementsByClassName('hitArea'),
    hitAreasLength = hitAreas.length;

while ( hitAreasLength-- > 0) {
    hitAreas[hitAreasLength].className = 'hitArea_practice';
}

Я не уверен, что это самый красивый код, но он работает :)

jsFiddle.

person alex    schedule 03.03.2011
comment
@alex Это не отвечает на вопрос. Возникает вопрос: почему цикл for...in выполняет итерацию не по всему DIV, а только по каждому другому DIV? - person Šime Vidas; 04.03.2011
comment
@ime Vidas Обычный цикл for тоже работает, и я в тупике. Только с помощью других методов отбора я смог добиться нормального поведения. - person alex; 04.03.2011
comment
@alex getElementsByClassName не работает, работает querySelectorAll. Это может быть связано с тем, что один из них является живым NodeList, а другой — нет. (Я не уверен, правда ли это, и если да, то какой из них какой, но это могло бы объяснить это.) - person Šime Vidas; 04.03.2011
comment
@alex getElementsByClassName — это активный список узлов. querySelectorAll — это неактивный список узлов. Я думаю, что это причина этой проблемы. - person Šime Vidas; 04.03.2011
comment
@Sime Vidas Спасибо, я посмотрю на это (и извиняюсь, скрипт, который я использовал для добавления имени ответа, пропустил Š в вашем имени ранее). - person alex; 04.03.2011
comment
@Šime Vidas Я обновил свой ответ, и этот работает. Спасибо за указание на это, я даже не подумал об этом. - person alex; 04.03.2011
comment
Живые списки могут застать вас врасплох, но они гладкие. На самом деле вы можете забыть length и просто сделать это: while ( hitAreas[0] ) { hitAreas[0].className = 'hitArea_practice'; } Поскольку вы полностью меняете className всех элементов, элемент с индексом [0] удаляется из списка на каждой итерации. - person user113716; 04.03.2011
comment
@patrick dw Спасибо, Патрик, я впервые сталкиваюсь с ним (обычно я использую jQuery), так что это действительно застало меня врасплох! Я запомню этот синтаксис на будущее, ура. - person alex; 04.03.2011
comment
Спасибо, парни. Это работало как ветер! Должен признаться, что я немного отстаю в своих знаниях JS, поэтому я обычно прибегаю к старым приемам. - person Eric; 04.03.2011