When running this code, the whatever value is first passed in with the constructor Test(callbacks) becomes the callback that is always called, even in later instantiations of Test
function Test(callbacks) {
if (callbacks) {
if (callbacks.callback) {
this.callback = callbacks.callback;
}
}
this.options.complete = $.proxy(this.options.complete, this);
}
Test.prototype = {
options: {
type: "GET",
complete: function() {
this.callback();
}
},
callback: function() { console.log("OVERRIDE ME"); },
execute: function() {
$.ajax(this.options);
}
};
var eins = {callback: function() {console.log("AAA");}};
var zwei = {callback: function() {console.log("BBB");}};
var A = new Test(eins);
var B = new Test(zwei);
A.execute();
B.execute();
Running this code, every time you will get the output AAA. How does function() {console.log("AAA");} become a constant value for the prototype?
It all starts with this line:
When you make a call
new Test(eins),einscomes in as thecallbacksargument. That line then setsthis.callback(ie. the “callback” property on your new instance of Test) to the callback property ofcallbacks, ie. ofeins.Now, that alone wouldn’t affect B. However, there’s something tricky:
You would think that that would set the “options” property on your Test instance, right? Wrong. The way Javascript works is that if a property isn’t defined on your instance (eg. you didn’t do
this.options = something) then Javascript will look up the “prototype chain”, where it will find the prototype’s “options”, and set it (not your instance’s “options”, since your instance doesn’t have one).You can fix all this by changing that line to:
but of course that would lose your
type: "GET",so either you need to do:or you need to base your options off the prototype’s:
If you happen to be using the (excellent) Underscore library, it even has an
extendfunction for doing this sort of thing more easily:Or (depending on your style preferences):
Incidentally, Underscore also has a
_.bindmethod which is comparable to jQuery’s “proxy”, so you could also do: