Значение “этого” в обработчике с помощью addEventListener

Я создал объект JavaScript через разработку прототипа. Я пытаюсь представить таблицу динамично. В то время как часть рендеринга проста и хорошо работает, я также должен обработать определенные клиентские события для динамично представленной таблицы. Это, также легко. То, где у меня есть проблемы, с "этой" ссылкой в функции, которая обрабатывает событие. Вместо "этого" ссылается на объект, он ссылается на элемент, который сгенерировал событие.

См. код. Проблематичная область находится в ticketTable.prototype.handleCellClick = function():

function ticketTable(ticks)
{
    // tickets is an array
    this.tickets = ticks;
} 

ticketTable.prototype.render = function(element)
    {
        var tbl = document.createElement("table");
        for ( var i = 0; i < this.tickets.length; i++ )
        {
            // create row and cells
            var row = document.createElement("tr");
            var cell1 = document.createElement("td");
            var cell2 = document.createElement("td");

            // add text to the cells
            cell1.appendChild(document.createTextNode(i));
            cell2.appendChild(document.createTextNode(this.tickets[i]));

            // handle clicks to the first cell.
            // FYI, this only works in FF, need a little more code for IE
            cell1.addEventListener("click", this.handleCellClick, false);

            // add cells to row
            row.appendChild(cell1);
            row.appendChild(cell2);


            // add row to table
            tbl.appendChild(row);            
        }

        // Add table to the page
        element.appendChild(tbl);
    }

    ticketTable.prototype.handleCellClick = function()
    {
        // PROBLEM!!!  in the context of this function, 
        // when used to handle an event, 
        // "this" is the element that triggered the event.

        // this works fine
        alert(this.innerHTML);

        // this does not.  I can't seem to figure out the syntax to access the array in the object.
        alert(this.tickets.length);
    }
65
задан Brian Tompsett - 汤莱恩 24 August 2019 в 10:02
поделиться

1 ответ

Вам необходимо «привязать» обработчик к вашему экземпляру.

var _this = this;
function onClickBound(e) {
  _this.handleCellClick.call(cell1, e || window.event);
}
if (cell1.addEventListener) {
  cell1.addEventListener("click", onClickBound, false);
}
else if (cell1.attachEvent) {
  cell1.attachEvent("onclick", onClickBound);
}

Обратите внимание, что обработчик событий здесь нормализует объект event (переданный в качестве первого аргумента) и вызывает handleCellClick в правильном контексте (т.е. ссылаясь на элемент, к которому был прикреплен прослушиватель событий).

Также обратите внимание, что здесь нормализация контекста (т.е. установка правильного this в обработчике событий) создает циклическую ссылку между функцией, используемой в качестве обработчика события ( onClickBound ), и объектом элемента ( cell1 ). В некоторых версиях IE (6 и 7) это может и, вероятно, приведет к утечке памяти. По сути, эта утечка связана с тем, что браузер не может освободить память при обновлении страницы из-за циклической ссылки, существующей между собственным и хост-объектом.

Чтобы обойти это, вам нужно будет либо а) удалить эту нормализацию; б) использовать альтернативную (и более сложную) стратегию нормализации; c) «очистить» существующие прослушиватели событий при выгрузке страницы, то есть с помощью removeEventListener , detachEvent и elements null ing (что, к сожалению, будет отображать быструю историю браузеров навигация бесполезна).

Вы также можете найти библиотеку JS, которая позаботится об этом. Большинство из них (например, jQuery, Prototype.js, YUI и т. Д.) Обычно обрабатывают очистку, как описано в (c).

detachEvent и elements null ing (что, к сожалению, сделает быструю навигацию по истории браузеров бесполезной).

Вы также можете найти библиотеку JS, которая позаботится об этом. Большинство из них (например, jQuery, Prototype.js, YUI и т. Д.) Обычно обрабатывают очистку, как описано в (c).

detachEvent и elements null ing (что, к сожалению, сделает быструю навигацию по истории браузеров бесполезной).

Вы также можете найти библиотеку JS, которая позаботится об этом. Большинство из них (например, jQuery, Prototype.js, YUI и т. Д.) Обычно обрабатывают очистку, как описано в (c).

42
ответ дан 24 November 2019 в 15:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: