jquery bind/trigger in a prototypal inheritance scenario. Can't trigger events on the right object
I'm trying to wrap my head around using bind/trigger in an inheritance scenario. Here is what I got:
var MyApp = {};
MyApp.GrandParent = function (){
var self = Object.create({}), $self = $(self);
self.doFoo = function(){
console.log('Just to asure we can call from child to grandpare开发者_StackOverflownt');
$(this).trigger('Happened');
//$self.trigger('Happened'); //Why doesn't it work this way
};
return self;
}
MyApp.Parent = function(){
var self = Object.create(MyApp.GrandParent()), $self = $(self);
self.doSomething = function(){
console.log('Just to asure we can call from child to parent');
$(this).trigger('SomethingHappened');
//$self.trigger('SomethingHappened'); //Why doesn't it work this way
};
return self;
}
MyApp.Child = function(){
var self = Object.create(MyApp.Parent()), $self = $(self);
$self.bind('SomethingHappened', function(){
console.log('Client logs: SomethingHappened');
});
$self.bind('Happened', function(){
console.log('Client logs: Happened');
});
return self;
}
var foo = new MyApp.Child();
foo.doSomething();
foo.doFoo();
Working Example: http://jsfiddle.net/cburgdorf/8fWta/12/
As you can see, we have an inheritance chain starting by the grandparent, over the parent to the child. It works. However, I just don't understand why I can't trigger the events on the $self object. It feels wrong to fire them on $(this).
What I want to archieve is to keep the prototype chain working and fire the events on the $self object. I guess I need to use something like $.proxy maybe but I really don't have a clue.
I know I could also do it like this http://jsfiddle.net/cburgdorf/8fWta/11/ but I would rather keep the prototype chain working...
Andy Edinborough is correct about var self != this
.
It looks like you want to store a reference to the jQuery wrapper around your object instances, so I used the flyweight pattern (avoids creating a property on the object instance to store the jQuery wrapper). You can read more about this at James Padolsey's blog.
I also cleaned up your code:
(function(window) {
var flyweight = $([1]);
/*--------------------------------------------------------------------------*/
function GrandParent() {
/* empty constructor */
}
function Parent() {
/* empty constructor */
}
function Child() {
flyweight[0] = this;
flyweight.bind('SomethingHappened', function(){
console.log('Client logs: SomethingHappened');
})
.bind('Happened', function(){
console.log('Client logs: Happened');
});
}
/*--------------------------------------------------------------------------*/
// setup inheritance
Parent.prototype = Object.create(GrandParent.prototype, {
'constructor': {
'configurable': true,
'writable': true,
'value': Parent
}
});
Child.prototype = Object.create(Parent.prototype, {
'constructor': {
'configurable': true,
'writable': true,
'value': Child
}
});
// add methods
GrandParent.prototype.doFoo = function(){
flyweight[0] = this;
flyweight.trigger('Happened');
};
Parent.prototype.doSomething = function(){
flyweight[0] = this;
flyweight.trigger('SomethingHappened');
};
/*--------------------------------------------------------------------------*/
// expose
window.MyApp = {
'GrandParent': GrandParent,
'Parent': Parent,
'Child': Child
};
}(this));
Usage check:
var foo = new MyApp.Child;
var bar = new MyApp.Child;
$(bar).bind('SomethingElse', function() {
console.log('Client logs: SomethingElse');
});
foo.doFoo(); // Client logs: Happened
foo.doSomething(); // Client logs: SomethingHappened
$(bar).trigger('SomethingElse'); // Client logs: SomethingElse
$(foo).trigger('SomethingElse'); // Nothing happens \o/
I think the problem is in your Object.create()
method: self !== this. It looks like self is being used as a prototype for the instance that is being created, and is not actually the same instance being returned.
It looks like this is what's happening in Child:
MyApp.GrandParent()
returns an instance ofGrandParent
--we'll call ita
.- The fields and functions of
a
are used to propogate a new instance ofParent
--we'll call itb
. - The fields and functions of
b
are used to propogate a new instance ofChild
--c
.
So the $self
reference in MyApp.GrandParent.doFoo
is actually a reference to a
--the original object, and this
is a reference to c
--the current object. That's why $(this).trigger(...)
works and $self.trigger(...)
doesn't.
In this fiddle, http://jsfiddle.net/andyedinborough/s8hV7/1/, I wrote the Object.create(...)
function to simply return the instance it was given, and $self.trigger(...)
works.
精彩评论