我可能做错了但是在尝试将一些面向对象的编程应用到Javascript时我发现了一些有趣的行为。请考虑以下
function Bug(element) {
this.focusedCell = null;
element.addEventListener('click', this.onClick, true);
};
Bug.prototype.onClick = function(event){
console.log("this is: ");
console.log(this);
};
当我从控制台调用该方法时,我看到了正确的“this”实例,但当我单击文档中的元素时,我看到文档元素代替实例。所以...使用实例方法的事件监听器可能不是一个好主意,至少我正在这样做。
所以问题是:
是否可以让这样的事件监听器调用javascript对象的实例方法,同时保留调用中的实例?
这样做有更好的模式吗?
编辑: 除了Chrome之外,我还没有尝试过这个。但我会想象行为是一样的。
答案 0 :(得分:6)
有一个更好的模式,并不需要太多改变。我将首先显示代码。
function Bug(element) {
this.focusedCell = null;
// --------------------------------v----pass the object, not a function
element.addEventListener('click', this, true);
};
// Implement the `EventListener` interface
Bug.prototype.handleEvent = function(event) {
if (event.type === "click")
this.onClick(event);
}
Bug.prototype.onClick = function(event) {
console.log(JSON.stringify(this)); // '{"focusedCell":null}'
console.log(event.currentTarget.nodeName); // "DIV"
};
通过添加handleEvent
方法,我们使Bug
实现EventListener
接口。这允许我们将新的Bug
对象作为第二个参数传递给addEventListener()
而不是函数。
现在,"click"
事件发生时,将调用.handleEvent()
方法,该方法中this
的值将是绑定的Bug
对象。
由于this
是对Bug
实例的引用,因此它显然不再是对该元素的引用。但是没有必要,因为元素可以通过event.currentTarget
获得。
当然,如果需要,您可以将元素直接添加到构造函数中的Bug
对象。
DEMO: http://jsfiddle.net/CnZTa/
答案 1 :(得分:5)
您可以使用Function.prototype.bind
创建一个绑定到所需此值的侦听器:
function Bug(element) {
this.focusedCell = null;
element.addEventListener('click', this.onClick.bind(this), true);
};
较旧的(非ES5)浏览器需要填充,例如来自MDN的填充。
答案 2 :(得分:1)
这是JavaScript中的正常行为。您可以通过向侦听器传递函数来保留预期的this
:
function Bug(element) {
var self = this; // Store a reference to this
this.focusedCell = null;
element.addEventListener('click', function() {
// in here this refers to element
self.onClick(event);
}, true);
};
Bug.prototype.onClick = function(event){
console.log("this is: ");
console.log(this); // In here this refers the an instance of Bug.
};