WelcomeTo
WelcomeTo

Reputation: 20581

Access to class member within closure

I have a class method and a closure within this method. How I can access to class member from closure?

Person = function(x) {
  this.x = x;
}

Person.prototype = {
   myMethod: function() {
      $('#myBtn').click( function() {
         // how to access to this.x? the this reference points in another context 
      });
   }
}

Upvotes: 4

Views: 902

Answers (4)

Mulan
Mulan

Reputation: 135237

Use of Function.prototype.bind will help you here

Person = function(x) {
  this.x = x;
}

Person.prototype.myMethod = function() {
  $('#myBtn').click(function() {
    this.x;
  }.bind(this));
};

You can use some better separation of code here too

Person = function(x) {
  this.x = x;
};

Person.prototype.myMethod = function {
  $('#myBtn').click(this.clickHandler.bind(this));
};

Person.prototype.clickHandler = function(event) {
  console.log(this.x);
};

Note if you want to support older browsers, check out es5-shim


EDIT

I'm revisiting this after ~6 months and I would probably write the above code differently. I like the private/public exposure here. Also, no need for any fanciful binds or anything like that ^.^

function Person(x, $button) {

  // private api
  function onClick(event) {
    console.log(x);
  }

  function myMethod() {
    $button.click();
  }

  // exports
  this.x        = x;
  this.myMethod = myMethod;

  // init
  $button.click(onClick);
}

var b = $("#myBtn"),
    p = new Person("foo", b);

p.x;          // "foo"
p.myMethod(); // "foo"
btn.click();  // "foo"

Upvotes: 9

Will M
Will M

Reputation: 2145

A proxy would be very useful here.

Right now, you're assigning an anonymous function to the click event. By default the context will be the event's and separate from your object.

With a proxy you can assign a particular context to a (callback) function. Thus, when the event fires, you're dealing with your person object.

  1. Assign the event handler in a separate function like initialize(), and have myMethod() be the handler.
  2. Use a JQuery.proxy() to assign the object`s context to the event handler.

    Person.prototype = {
        initialize: function() {
            $('#myBtn').click($.proxy(this.myMethod, this));
        },
    
        myMethod: function(event) {
         ...
         console.log(this); // Person object
        }
    }
    

Just to elicit the difference between my and @naomik's solution:

  • JQuery.proxy() is a temporary or narrow assignment to a context.
  • Function.prototype.bind() is a strong context assignment. The method will be "forever" bound to the context you give it.

Upvotes: 0

adjogima
adjogima

Reputation: 169

Person = function(x) {
  this.x = x;
}

Person.prototype = {
   myMethod: function() {
      var self = this;
      $('#myBtn').click( function() {
         // Access to self.x 
      });
   }
}

Upvotes: 1

skimberk1
skimberk1

Reputation: 2094

Just assign this to some other variable, for example _this:

Person = function(x) {
    this.x = x;
}

Person.prototype = {
    myMethod: function() {
        var _this = this;
        $('#myBtn').click( function() {
            console.log(_this.x);
        });
    }
}

Upvotes: 2

Related Questions