Reputation: 4268
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:
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.
Upvotes: 1
Views: 144
Reputation: 83358
EDIT
Here's the answer to your question
$(document).ready(function(){
alert('1');
var a = new Abc();
var x = new Xyz({listenFn: a.onEvent.bind(a) }); // <------- bind
x.execute();
});
Using bind like this will pre-set the this
value inside of a.onEvent to be a
. Just note that IE8 does not support bind
, but you can easily add a shim from here.
The other way to do this would be to say:
$(document).ready(function(){
alert('1');
var a = new Abc();
var x = new Xyz({listenFn: function() { a.onEvent() });
x.execute();
});
Without diving too deeply into your code, I'll just say this: figuring out the value of this
in 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*, this
will be equal to x
inside of foo.
If you have foo()
, then, no matter what*, this
will be the global object, or undefined in strict mode inside of foo.
If you say new foo()
then this
will be a new object whose prototype will be set to foo.prototype
If you say foo.call(a)
, there this
will be a
* inside of foo, but that doesn't really apply here.
*The one exception being that if you had declared foo as
var foo = function() { }.bind(obj);
then you've pre-bound this
to be obj
for all calls of foo, and will override the rules above.
Upvotes: 3