4

I'm a C++ guy just learning JavaScript, so the fact that 'this' is bound to the calling object continues to surprise. I want to use an object method as an event listener, and want to make sure I am doing it with all the style of you JavaScript professionals.

So, to get the method to have it's objects 'this', so that I can access its properties in the proper context, I have written the following:

var user =
{
    status: 1,      // login status: 0:invalid password, 1:logged out, 2:logged in
loginName: "",

// Method called whenever the user submits a username/password via html form:
onLoginSubmit: function (event)
{
        if (this != user)   // called from 'form submit' callback, so call ourselves:
    {
        user.onLoginSubmit(event);
        return;
    }
}
};

I found a previous answer here: Accessing an object's property from an event listener call in Javascript, but the proposed solution is to basically create a global. Is there a cooler, more professional way to get 'this' than the previous solution or my recursive solution?

Community
  • 1
  • 1
Steger
  • 887
  • 7
  • 16

3 Answers3

3

I'm assuming that when you are binding the submit handler, you are doing something like this:

form.submit(user.onLoginSubmit);

While what you have does work, the best way to do with would be to bind the submit handler so that it actually calls onLoginSubmit with the proper 'this', so that you don't need any extra logic inside the submit handler.

If you do something like this when you bind the function, then it should work.

form.submit(function(e) {
  user.onLoginSubmit(e);
});

By using an anonymous function, you can still properly call the method of the user object.

If I'm misunderstanding your issue, please post a bit more code about how you are calling onLoginSubmit().

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • An important thing about js is closures like this. And anonymous functions. Oh, and did I mention closures? Those are REALLY important. – Alxandr Sep 01 '11 at 00:08
  • This is what I was looking for! And also to know that there was nothing really stupid I was/wasn't doing... The anonymous function technique moves the weirdness out of my class method to where it belongs. Thanks. – Steger Sep 01 '11 at 01:16
0

Might be a little late to the party but I'll leave this for anyone interested...

I really don't like how events change context, there is already a target object in the event you can reference, so I don't know why it does?

I add the listeners like this so it doesn't happen:

addEventListener('click', (event)=>{handle(event)});
-OR-
addEventListener('click', function(event){handle(event)}); //No lamda

This way the context of your handling function stays the same and you still have the event object passed through. You can reference the target in the event to get what 'this' would have been originally. Keep in mind that 'this' will now be the context that the anonymous function was called under... should be your instance if called in a class, constructor, or method.

0

You could use closures, this should work :

function User() {

  var that = this;
  this.status = 1;
  this.loginName = "";
  this.onLoginSubmit = function (event)
  {
     // the variable "that" is available and references the User instance
  }
}
var user = new User();

Here we use User as a constructor, so this points to the object being constructed via "new". What happens (roughly) is that the "that" variable is local to the User function, but since a function references it it stays in memory and is available to this function. You're then able to use "that" instead of "this" as a "fake" scope.

This is not something you would want to use if you have a lot of User instances, because the functions are created for each instance. The "regular" way would be to use an anonymous function like in Logan's answer.

Most (if not all) frameworks have elegant ways for handling this, but basically you either need to have the scope available in the function itself via closure, or know it when you call the function so you can do it with the right scope (by writing user.onLoginSubmit() )

Hope this kinda clear :)

edit: oh well someone posted kind of the same thing in the post you linked. Well now you have it tailored to 'user'!

Jad
  • 922
  • 8
  • 14
  • Thanks for the response. I now see that 'that' is not global -- it has function scope. I only have one User object, but if I had more than one, there would still only be one 'that', correct? – Steger Sep 01 '11 at 01:20
  • since 'that' is local, each User instance would have its own copy (and its own onLoginSubmit method) – Jad Sep 01 '11 at 07:58