aw crud
aw crud

Reputation: 8891

The value of 'this' inside of a Javascript prototype function used as an event handler

I'm trying to use prototype inheritance in Javascript. The problem with my code below is that when the button is clicked and MyNamespace.MyObj.myEventHandler is called, the value of this is not the instance of MyNamespace.MyObj, but is instead the button that was clicked.

Am I structuring things wrong (is there a better way)? Can I somehow ensure that this is the instance of the object rather than the caller button?

var MyNamespace.MyObj = function(myform) {
  this.myform = myform;
  jQuery('.mybutton', this.myform).click(this.myEventHandler);
};

MyNamespace.MyObj.prototype = {
  myEventHandler: function() {
    this.myform.get(0).submit();
  }
};

jQuery(document).ready(function() {
  new MyNamespace.MyObj(jQuery('#myform'));
});

This is just a very dumbed down example that I'm using to learn prototype inheritance. I realize the actual function of the above code could be done simply in jQuery or that I could use an object literal or the Module pattern -- but I'm really just interested in learning the prototype inheritance rather than implementing a specific function at this time.

Upvotes: 1

Views: 282

Answers (2)

Sean McMillan
Sean McMillan

Reputation: 10093

If you have access* to the es5 Function.prototype.bind, you can do this:

jQuery('.mybutton', this.myform).click(this.myEventHandler.bind(this));

jQuery provides jQuery.proxy, which does the same thing, but with different syntax:

jQuery('.mybutton', this.myform).click(jQuery.proxy(this.myEventHandler, this));

Both of these work with a method and an object, and return a function that will call that method on that object.

When you pass (or assign) a method in javascript, it gets sliced off of the original object. This is just one of those things you have to know. (This is the same thing that makes inheritance work, actually. Methods get sliced off of the parent, and are invoked in the context of the child.)

*Say, via the es5 shim.

Upvotes: 0

Christian C. Salvadó
Christian C. Salvadó

Reputation: 827396

There are various ways to preserve the this value, the most simple IMO is:

var MyNamespace.MyObj = function(myform) {
  var instance = this; // store `this`
  this.myform = myform;
  jQuery('.mybutton', this.myform).click(function () {
    instance.myEventHandler(); // use the stored value
  });
};

Upvotes: 5

Related Questions