当前位置: 首页 > 面试题库 >

使用addEventListener的处理程序中“ this”的值

乐正意智
2023-03-14
问题内容

我已经通过原型创建了一个Javascript对象。我正在尝试动态呈现表。尽管呈现部分很简单并且可以正常工作,但我还需要为动态呈现的表处理某些客户端事件。那也很容易。我遇到问题的地方是处理事件的函数内部的“
this”引用。而不是“ this”引用对象,而是引用引发事件的元素。

参见代码。问题区域在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);
    }

问题答案:

您需要将处理程序“绑定”到您的实例。

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)中,这可能会并且可能会导致内存泄漏。本质上,此泄漏是由于本机和主机对象之间存在循环引用,浏览器无法在页面刷新时释放内存。

为了规避它,您将需要:a)删除this规范化;b)采用替代(且更为复杂)的标准化策略;c)在页面卸载时“清理”现有的事件侦听器,即使用removeEventListenerdetachEvent和元素nulling(不幸的是,这将使浏览器的快速历史导航无效)。

您还可以找到一个负责此工作的JS库。它们中的大多数(例如:jQuery,Prototype.js,YUI等)通常按照(c)中所述进行清理。



 类似资料:
  • 我已就有关守则作出评论。我通过反复试验发现,我必须在事件处理程序和命名回调中都使用bind,才能使事情正常工作。

  • 我需要检查用户在请求websocket连接时是否提供了有效的令牌。对于验证,调用验证服务器是必要的。我如何同步实现它,以便websocket处理程序不会在有答案之前结束。我正在使用vertx框架。

  • 玩一些es6,遇到了一个问题,我不知道如何解决 在的内部,?目前我用bind解决了这个问题,但我想知道是否有一种更“合适”的ES6方法来实现这一点。

  • 我有一个带post请求的控制器。我试图用一个简单的NotNull注释验证POJO。我正在使用ControllerAdvice来处理异常。 所以我尝试使用它,但当我启动应用程序时,我得到了以下信息: 因此,我想为BindException创建自己的处理程序,但当我为BindException类创建ExceptionHandler时,spring应用程序不会启动。如果我注释掉handleBindExc

  • 我正在使用vertx的JDBC lib,我需要批量插入包含数组字段的值。 我试过: 我的输出: 在切换到准备好的报表之前,我的工作要求是: 我的数据库是Apache Phoenix,是Hbase的sql层。 知道怎么解决吗?

  • 很抱歉,我对Java还是一个新手,我试图通过在线帮助来解决这个问题。我正在尝试一个try/catch来处理“输入学生的作业成绩”之后的InputMismatchException(以防他们输入的是字母而不是数字)。到目前为止还没有结果。要实现这一点,代码应该是什么样子的? 编辑:不,伙计们,重复扫描仪不是我的问题。我无法成功处理InputMismatchException,我已经尝试了几个小时。请