Reputation: 17
I have the following Javascript,
eventManager: {
$musicGenres : null, // $musicGenres is the selector for a div-container of inputs
musicGenres : [],
// Functions
handle : function(selectors) {
selectors = (typeof selectors === 'undefined') ? {
'musicGenres' : '#musicGenres'
} : selectors; // selectors default values...
this.$musicGenres = $(selectors['musicGenres']);
console.log("CHANGED $musicGenres TO " + this.$musicGenres);
this.$musicGenres.find('input').change(this.reloadMusicGenres);
},
reloadMusicGenres : function() {
console.log("IN FUNCTION $musicGenres IS " + this.$musicGenres);
},
, call the function eventManager.handle()
on my page and trigger the change-Event of one of those inputs, which outputs
CHANGED $musicGenres TO [object Object]
IN FUNCTION $musicGenres IS undefined
what I don't understand. I've set $musicGenres to a new value, but in the reloadMusicGenres-function it stays undefined. Even when I manually access $musicGenres' value through the console by typing in eventManager.$musicGenres
it outputs the right value.
Could anybody help me? That really worries me.
Upvotes: 1
Views: 470
Reputation: 9388
The context
of this
has changed. The easiest way to address the issue is to reference this
outside the function, or pass a data
object (as suggested by the two other fine posters, Richard Healy and AlliterativeAlice).
A third way is to explicity bind
the context of this
. Using jQuery, you can achieve this by calling $.proxy
. So, this:
this.$musicGenres.find('input').change(this.reloadMusicGenres);
becomes:
this.$musicGenres.find('input').change($.proxy(this.reloadMusicGenres, this));
$.proxy
will return a new function, where this
will always be bound to eventManager
. If you're interested in moving away from jQuery, Function.prototype.bind
is your answer (Edit: an example of which is provided by Zoltan's answer)
Here's some links for documentation on how to use these fine functions:
jQuery proxy: https://api.jquery.com/jQuery.proxy/
Bind function: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
Upvotes: 2
Reputation: 2871
As others already pointed out, your problem is context binding.
IMO the easiest way to fix your code would be to change this line
this.$musicGenres.find('input').change(this.reloadMusicGenres);
to this:
this.$musicGenres.find('input').change(this.reloadMusicGenres.bind(this));
This should solve your problem. No need to change anything else in your code.
Upvotes: 2
Reputation: 12577
You can pass the object to the change handler like this:
this.$musicGenres.find('input').change(this, this.reloadMusicGenres);
Then in reloadMusicGenres()
:
reloadMusicGenres : function(e) {
console.log("IN FUNCTION $musicGenres IS " + e.data.$musicGenres);
}
Upvotes: 1
Reputation: 599
Have you tried in the handle method:
var self = this;
this.$musicGenres.find('input').change(function () {
self.reloadMusicGenres();
});
Might be a scoping issue when the reloadMusicGenres function gets called.
Upvotes: 2