3

So I have most of my functions and variables organized into small object-based modules, like so:

module1: {
  someVariable: false,

  someFunction: function(e) {
     do some stuff using someVariable
  },

  someFunction2: function(e) {
    do some other stuff
  }
}

And I call these functions as callbacks during various events, like so:

$(function() {
  $('.thing').on('mouseenter', module1.someFunction);
}

Now, from within someFunction, I would expect the 'this' keyword to refer to the object in which the function is contained. Instead, it refers to the DOM element that triggered the event that fires the function. Is there anyway I can get access to, say the someVariable variable in the function's containing object other than writing module1.someVariable?

user1427661
  • 11,158
  • 28
  • 90
  • 132
  • 2
    event handlers always have a context of the element that the event was triggered on unless otherwise specified. you can specify a specific context using Function.bind, $.proxy, or by using an anonymous function and storing a reference to the context you want. – Kevin B Oct 17 '13 at 17:18
  • 1
    Possible duplicate of [In Javascript, why is the “this” operator inconsistent?](http://stackoverflow.com/q/80084/710446), but you might find my answer on [Understanding Javascript scope with “var that = this”](http://stackoverflow.com/a/12371105/710446) to be more directly focused on your particular problem. – apsillers Oct 17 '13 at 17:21

1 Answers1

4

The shortest answer is to try this:

$(function() {
  $('.thing').on('mouseenter', function(e) {
    module1.someFunction(e);
  });
}

The 'this' value is only set to the object the method is attached to if the method is invoked directly on the object:

module1.someFunction(); // direct invocation, 'this' will be set properly
var tempFunc = module1.someFunction;
tempFunc(); // the function was removed first.  'this' will NOT be set

In your case, you are pealing the method off of the object and handing it to an event handler. The event handler doesn't know about the object and doesn't perform a direct invocation.

In fact, the event handler explicitly overrides the context because that is how the jQuery API is defined. You have to explicitly override it back if you want the behavior you're talking about.

Using a library like underscore.js you could also bind the function as you pass it off to the event handler.

$(function() {
  $('.thing').on('mouseenter', _.bind(module1.someFunction, module1));
}

I believe that Object.bind is supposed to be natively supported in the future with no libraries, but you can't yet rely on the older browsers to support it.

Mike Edwards
  • 3,742
  • 17
  • 23
  • http://fiddle.jshell.net/LxdAz/ - In this fiddle you can see how these two different types of event calls work. Note how I get the DOM object targeted in the event `$(e.currentTarget)` which is what jQuery passes as `this`. – iambriansreed Oct 17 '13 at 17:39