“this”的值在使用addEventListener的处理程序中 [英] The value of "this" within the handler using addEventListener
问题描述
我通过原型设计创建了一个javascript对象。我正在尝试动态呈现表格。虽然渲染部分很简单并且工作正常,但我还需要处理动态渲染表的某些客户端事件。那也很容易。我遇到问题的地方是处理事件的函数内部的this引用。它不是this引用对象,而是引用引发事件的元素。
I've created a javascript object via prototyping. I'm trying to render a table dynamically. While the rendering part is simple and works fine, I also need to handle certain client side events for the dynamically rendered table. That, also is easy. Where I'm having issues is with the "this" reference inside of the function that handles the event. Instead of "this" references the object, it's referencing the element that raised the event.
请参阅代码。有问题的区域在ticketTable.prototype.handleCellClick = function()
See code. The problematic area is in "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);
}
推荐答案
你需要绑定你的实例的处理程序。
You need to "bind" handler to your instance.
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);
}
请注意,此处的事件处理程序规范化事件
object(作为第一个参数传递)并在适当的上下文中调用 handleCellClick
(即引用附加事件监听器的元素)。
Note that event handler here normalizes event
object (passed as a first argument) and invokes handleCellClick
in a proper context (i.e. referring to an element that was attached event listener to).
另请注意,此处的上下文规范化(即在事件处理程序中设置正确的此
)会在用作事件处理程序的函数之间创建循环引用( onClickBound
)和一个元素对象( cell1
)。在某些版本的IE(6和7)中,这可能并且可能会导致内存泄漏。这种泄漏本质上是由于本机和主机对象之间存在循环引用而导致浏览器无法在页面刷新时释放内存。
Also note that context normalization here (i.e. setting proper this
in event handler) creates a circular reference between function used as event handler (onClickBound
) and an element object (cell1
). In some versions of IE (6 and 7) this can, and probably will, result in a memory leak. This leak in essence is browser failing to release memory on page refresh due to circular reference existing between native and host object.
要规避它,你需要a)放弃这个
规范化; b)采用替代(和更复杂)的规范化战略; c)在页面卸载时清理现有的事件监听器,即使用 removeEventListener
, detachEvent
和元素 null
ing(遗憾的是,这会导致浏览器的快速历史导航失效)。
To circumvent it, you would need to either a) drop this
normalization; b) employ alternative (and more complex) normalization strategy; c) "clean up" existing event listeners on page unload, i.e. by using removeEventListener
, detachEvent
and elements null
ing (which unfortunately would render browsers' fast history navigation useless).
您还可以找到一个小心的JS库这个的。其中大多数(例如:jQuery,Prototype.js,YUI等)通常处理(c)中描述的清理。
You could also find a JS library that takes care of this. Most of them (e.g.: jQuery, Prototype.js, YUI, etc.) usually handle cleanups as described in (c).
这篇关于“this”的值在使用addEventListener的处理程序中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!