I'm making a custom editor for slickgrid, although I doubt what I'm doing really matters in this case. So let's say I have something like this vaguely setup:
function TestEditor(args) {
var $test0, $test1;
//other variables
this.init = function () {
//various init stuff, it all works fine
//init $test0 and $test1, also works fine
$test0.bind("change", this.test0Changed);
$test1.bind("change", this.test1Changed);
this.test0Changed(); //this works fine too, makes the nested call to test1Changed
}
this.test0Changed = function() {
//does various operations
this.test1Changed(); //calls test1Changed, this works _unless_ test0Changed is called through an event, then the code breaks here!
//stuff that won't happen when the code breaks at the previous call
}
this.test1Changed = function() {
//stuff, works fine unless called by test0Changed triggered by an event, then nothing
}
//whatever, lots of other stuff, it all works
this.init();
}
I want test0Changed to make a call to test1Changed, and it works fine if I explicitly make the call myself to this.test0Changed() in the code. But when test0Changed is triggered by the 'change' event, the code breaks when it tries to call this.test1Changed(). If I comment out the call to this.test1Changed(), everything is fine, so I know it's that precise line that is causing the problem. What is causing this?
It's because when you the function to .bind()
, it doesn't "remember" the intial this
value.
As a handler, this
will be the element that received the event.
this.init = function () {
var self = this;
$test0.bind("change", function() {self.test0Changed.apply(self, arguments);});
$test1.bind("change", function() {self.test1Changed.apply(self, arguments);});
}
Here I referenced the this
you want to use in a variable, and I passed anonymous functions that use that referenced this
value to call the functions.
I also used .apply
to ensure that all the original arguments are passed on. If that isn't necessary, you could change it to this...
this.init = function () {
var self = this;
$test0.bind("change", function() {self.test0Changed();});
$test1.bind("change", function() {self.test1Changed();});
}
Or you could use jQuery's $.proxy
to retain the this
value...
this.init = function () {
$test0.bind("change", $.proxy(this, 'test0Changed'));
$test1.bind("change", $.proxy(this, 'test1Changed'));
}