I’m using multiple prototypes to manage some complex situations and I’m having trouble with the use of ‘this’. I’m not 100% certain how to describe as I’m not familiar with the correct terminology, but I’ll have a go.
Function X has a variable that points to a function within function Y. This method within function Y wishes to access a variable that is within the scope of the function Y, but when I use this, it refers to function X.
I’ve created a JSFiddle with an example, using prototypes and so on (as that is the scenario that I find myself in). However the code is short, so I’ll include it below:
var Abc = function(options) {
alert('2');
options = options || {};
this.myVar = options.myVar || 'Abc.myVar';
};
Abc.prototype = {
onEvent: function() {
alert('myVar: ' + this.myVar);
}
};
var Xyz = function(options) {
alert('3');
options = options || {};
this.listenFn = options.listenFn || function() {
alert('x');
};
this.myVar = options.myVar || 'Xyz.myVar';
};
Xyz.prototype = {
execute: function() {
alert('4');
this.listenFn();
}
};
$(document).ready(function(){
alert('1');
var a = new Abc();
var x = new Xyz({listenFn: a.onEvent});
x.execute();
});
I’ve put in alerts in sequence of the code execution. So:
- is the start of the document ready.
- is the creation of the Abc instance.
- is the creation of the Xyz instance, where the onEvent function for the instance of Abc is assigned to the listenFn for Xyz.
- is inside the point where execute on Zyz has been called which in turn calls the onEvent of Xyz and it displays the value for this.myVar.
The problem I have is that ‘this’ is referring to the Xyz instance when inside a method on Abc. I need to be able to set/get the value of myVar for the instance of Xyz. I suspect I could do something messy with creating a function that is passed into the new Xyz statement and thus have the instance of Abc passed back to itself, but unfortunately this is not possible with what I am working with (also not very elegant).
Cheers.
EDIT
Here’s the answer to your question
Using bind like this will pre-set the
thisvalue inside of a.onEvent to bea. Just note that IE8 does not supportbind, but you can easily add a shim from here.The other way to do this would be to say:
Without diving too deeply into your code, I’ll just say this: figuring out the value of
thisin JavaScript is quite easy; it all depends on the manner in which the function is called.If you have
x.foo(), then, no matter what*,thiswill be equal toxinside of foo.If you have
foo(), then, no matter what*,thiswill be the global object, or undefined in strict mode inside of foo.If you say
new foo()thenthiswill be a new object whose prototype will be set tofoo.prototypeIf you say
foo.call(a), therethiswill bea* inside of foo, but that doesn’t really apply here.*The one exception being that if you had declared foo as
then you’ve pre-bound
thisto beobjfor all calls of foo, and will override the rules above.