addEventListener в JS не работает должным образом

Сначала просмотрите коды, пожалуйста.

index.html это:

Home




    
        <a href="#" class="supcont">Home</a>
        
            <a href="#" class="subcont">Home1</a>
            <a href="#" class="subcont">Home2</a>
            <a href="#" class="subcont">Home3</a>
        
    

    
        <a href="#" class="supcont">Blog</a>
        
            <a href="#" class="subcont">Blog1</a>
            <a href="#" class="subcont">Blog2</a>
            <a href="#" class="subcont">Blog3</a>
        
    





script.js это:

function init() {
    var sky = 0;
    var sup         = document.getElementById("sup");
    var supitems    = sup.getElementsByClassName("supitem");

    for (var i = 0, ln = supitems.length; i < ln; i++) {
        var supconts = supitems[i].getElementsByClassName("supcont");
        var subs = supitems[i].getElementsByClassName("sub");
        var supcont = supconts[0];

        supcont.innerHTML = "SuperMenu"+i;

        if (subs.length > 0) {
            var sub         = subs[0];

            supcont.addEventListener("click",function() {
                toggleVisibility(sub); });

            supcont.style.background = "#"+sky+sky+sky;
            sub.style.background = "#"+sky+sky+sky;
            sky += 4;
        }
    }
}

function toggleVisibility(object) {
    object.style.visibility =
        (object.style.visibility == "hidden" ?"visible" :"hidden");
}

То, что я хотел бы сделать, это когда я нажимаю суперменю все подменю видимость для переключения. Но я неНе знаю, где я допустил ошибку. Когда я нажимаю Supmenu0, переключаются подменю Supmenu1, а не подменю Supmenu1. Заранее спасибо.

Постскриптум Я думаю, что проблема в addEventListener.

Ответы на вопрос(1)

но я постараюсь дать лучшее объяснение, чем я нашел. Когда вы передаете функцию в качестве параметра (как при определении вашего обработчика события), javascript не оценивает функцию в это время, а вместо этого сохраняет функцию вместе со ссылкой на ее родителя.scope

Функция не оценивается, пока не сработает обработчик события. В это время переводчик проверит значениеsub в родительскомscope, Так как это всегда будет происходить после вашегоfor цикл завершен, он всегда найдет последнее значениеsubто естьsub был когда твойfor цикл был завершен. Таким образом, все ваши слушатели событий будут использовать последнее значение.sub

Мы можем получить желаемое поведение, создавзакрытие, Заменить это:

supcont.addEventListener("click",function() {
    toggleVisibility(sub); });

с этим:

(function(localSub) {
    supcont.addEventListener("click",function() {
        toggleVisibility(localSub);
    });    
})(sub);

Причина, по которой это работает, заключается в том, что мы обертываем каждое объявление обработчика события новым родителемscope вызывая IIFE. Это заставляет обработчик событий сохранять копиюscope внутри IIFE (называется создание закрытия над этимscope). Теперь, когда обработчик событий ищетlocalSub, он найдет его у нового родителяscope и это будет иметь значение, которое мы хотим.

 accidentallygivenfuck15 мая 2013 г., 17:26
Спасибо, сэр. Кстати, я только что узнал, что такое закрытие. Оставив ссылку здесь это на всякий случай:stackoverflow.com/questions/111102/... :)

Ваш ответ на вопрос