Usually I use objects in JavaScript to save data, but event listeners do not allow auxiliary pointers to retrieve these objects.
What is the best way to retrieve an object pointer in an event callback? (Without 3rd party libraries please)
Example:
function MyClass()
{
this.number = Math.random();
this.button = document.createElement('div');
this.button.appendChild(document.createTextNode('Show number'));
document.body.appendChild(this.button);
// THIS FOLLOWING LINE REQUIRE CHANGES
this.button.addEventListener('click', MyClass.prototype.listener);
}
MyClass.prototype.listener = function (e)
{
// HERE, "THIS" DO NOT POINT TO MY OBJECT
alert( this.number );
}
testMyClass1 = new MyClass();
testMyClass2 = new MyClass();
Currently, I use a static array to save pointers, but that is hard to maintain:
//New constructor, first try
function MyClass()
{
this.number = Math.random();
this.button = document.createElement('div');
this.button.appendChild(document.createTextNode('Show number'));
document.body.appendChild(this.button);
if (undefined===MyClass.prototype.register) MyClass.prototype.register = [];
this.id = MyClass.prototype.register.length;
MyClass.prototype.register.push(this);
this.callback = new Function( 'e',
'var self = MyClass.prototype.register[' + this.id + '];'+
'MyClass.prototype.listener.call(self, e);'
);
this.button.addEventListener('click', this.callback);
}
NOTES:
If using ES5:
this.button.addEventListener('click', MyClass.prototype.listener.bind(this));
If not using ES5, get a shim for Function.bind
.
Note that this does actually create a new function object as the handler for each instance of your class, but there's no easy way to avoid that.
You can use Function.bind
to set the context of an event handler
function MyClass()
{
this.number = Math.random();
this.button = document.createElement('div');
this.button.appendChild(document.createTextNode('Show number'));
document.body.appendChild(this.button);
// THIS FOLLOWING LINE WAS CHANGED
this.button.addEventListener('click', MyClass.prototype.listener.bind(this));
}
MyClass.prototype.listener = function (e)
{
// HERE, "THIS" DO NOT POINT TO MY OBJECT
alert( this.number );
}
testMyClass1 = new MyClass();
testMyClass2 = new MyClass();
A very simple and elegant way is to make your object implement the EventListener interface.
To do this, your object simply needs to have a handleEvent()
method.
MyClass.prototype.handleEvent = function(event) {
switch (event.type) {
case "click":
return this.listener(event);
default:
throw "No handler for " + event.type
}
}
Then you just pass the object itself.
// v--pass the object instead of a function
this.button.addEventListener('click', this);
So this
in handleEvent
is the expected object, so you can just call your object methods.
You can simply use a function to create a wrapper that takes fewer parameters. In other words,
Change:
this.button.addEventListener('click', MyClass.prototype.listener);
To:
var self = this;
this.button.addEventListener('click', function() { self.listener(); });
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.