addEventListener передает вызывающего в качестве аргумента - PullRequest
2 голосов
/ 18 апреля 2010

У меня есть следующий код. И моя проблема в том, что при нажатии событие запускается, но переданный аргумент не является правильным. Он передает последнюю динамически созданную строку, то есть значение dataStructure.length. Кто-нибудь знает решение, как обойти это?

        var table = document.getElementById('output');                  

        for(i =0; i<dataStructure.length; i++){
            var row = document.createElement('tr');
            row.setAttribute('id', i);
            var url = dataStructure[i].url;

            if(document.addEventListener)
                row.addEventListener('click', function(){handleRowClick(i);}, false);
            var obj = dataStructure[i];
            var cellCount = 0;
            for(field in obj){
                var cell = document.createElement('td');
                cell.setAttribute('id', cellCount++);
                //cell.addEventListener('click', function(){window.open(dataStructureObj.links[i].url);}, false);
                cell.innerHTML = obj[field];
                row.appendChild(cell);
            }
            cellCount = 0;
            table.appendChild(row);
        }           
        }

        function handleRowClick(rowClicked){
            var rowHTML = rowClicked.innerHTML;
            var cells = rowHTML.getElementsByTagName('td');
            for(cell in cells)
            {
                alert(cell.value);
            }
            window.open(cells[1].innerHTML); 
        }

1 Ответ

2 голосов
/ 18 апреля 2010

i в function(){handleRowClick(i);} является переменной цикла i. Когда функция вызывается, цикл завершается долго и i содержит последнее значение, которое было сделано в конце цикла, не значение, которое оно удерживало при создании function(){}.

Это проблема замкнутого цикла. См. этот вопрос для решений, использующих замыкания или Function#bind:

row.addEventListener('click', handleRowClick.bind(window, i), false);

Однако в данный момент вы не используете этот i. Было бы проще сказать:

row.addEventListener('click', handleRowClick, false);

, а затем используйте this, чтобы получить строку:

function handleRowClick(){
    window.open(this.cells[1].innerHTML);
}

(Примечание: к сожалению, если вы добавите attachEvent резервную копию для поддержки IE <= 8, она не получится правильной <code>this, поэтому вы все равно будете смотреть на замыкания / привязки, чтобы получить объект, который вы хочет.)

также:

    for(i =0; i<dataStructure.length; i++){

Отсутствует var: i - это случайный глобал.

        row.setAttribute('id', i);

Избегайте getAttribute / setAttribute в документах HTML. Они не делают то, что должны в IE. Вместо этого используйте HTML-свойства DOM Level 2, они более надежны и удобочитаемы: row.id= i.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...