I'm trying to bind a javascript object to an event listener and this is how I'm going about it: (this is a simplified example, but it uses the pattern I'm interested in)
function foo(x){
this.x = x;
}
foo.prototype = {
'bar': function(){
// do something with this.x
},
'events': function(){
$(document).on('custom_event', function(event, x){
var G = new foo(x);
G.bar();
});
}
};
(function(){
var G = new foo();
G.events();
})();
So after the self-invoking anonymous function is run, every time custom_event
is fired the bar method of my foo object will be called.
Questions:
When new foo(x)
is called from within the event handler of my foo object, does it cause a duplication of the event listener?
It is my understanding that prototype
methods belonging to an object are only created once and that calling new foo()
only effects, in my case, this.x
. If I am correct, I'm confused why it's necessary to use new
from within the event listener in foo
's events
method in order to use the prototype methods attached to foo
.
What am I missing?
It seems you're mainly confused about the usage and effects of the new
operator. I quote from You Don't Know JS, this & object prototypes :
When a function is invoked with
new
in front of it, otherwise known as a constructor call, the following things are done automatically:
- a brand new object is created (aka, constructed) out of thin air
- the newly constructed object is
[[Prototype]]
-linked- the newly constructed object is set as the
this
binding for that function call- unless the function returns its own alternate object , the
new
-invoked function call will automatically return the newly constructed object.
Make sure you understand that well. On your questions:
When
new foo(x)
is called from within the event handler of my foo object, does it cause a duplication of the event listener?
No. What you do with new foo(x)
is use the foo
function as a constructor, so you're only creating a new, prototypally linked, object (similar to {}
) and then executing the code inside foo
, with that new object as this
. So that will result in an almost empty object, except for its property x
. You're only setting up the event listener inside the events
function!
It is my understanding that
prototype
methods belonging to an object are only created once and that callingnew foo()
only effects, in my case,this.x
. If I am correct, I'm confused why it's necessary to usenew
from within the event listener infoo
'sevents
method in order to use the prototype methods attached tofoo
.
They are defined once, on the object you refer to as "the prototype" (which is really just the prototype
property on the function foo
), yes. And it's not necessary to use new
here, all you're doing with that is creating a throwaway foo
object inside a function of an already existing foo
object.
What you'll likely want to do is not worry about setting this.x
inside the constructor, but inside the event handler, before calling bar()
:
something.on('custom_event', function(e, x) {
this.x = x;
this.bar();
});
The problem that you'll encounter here is that this
in the context of the event handler will most likely be set/overridden by jQuery, and not point to the " foo
object" you want to point to. To circumvent this problem, you need to either lexically capture the this
at the moment of setting up the event handler (which is the events
function):
events: function(){
var self = this;
$(document).on('custom_event', function(event, x){
self.x = x;
self.bar();
});
}
or bind
the this
inside the callback handler to the " foo
object" you want to reference:
events: function(){
$(document).on('custom_event', (function(event, x){
this.x = x;
this.bar();
}).bind(this));
}
See Function.prototype.bind on MDN for some explanation of what this does.
Further note: I'm not sure what your custom event really is, but you're listening on the entire $(document)
inside every single event handler. If you have DOM elements corresponding to each foo
object, you should instead set these event handlers up on these specific DOM elements.
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.