views:

187

answers:

5

Let's say I have a very simple PrototypeJS class that looks like this:

var Foo = Class.create({
  initialize:  function() {
    this.bar = 'bar';
  },

  dostuff:  function() {
    $$('.enabled').each( function(elem) {
      alert(this.bar);  //FAIL
    });
  }
});

This fails because the function being passed to .each() doesn't have any idea what this refers to.

How can I access the bar attribute of the Class from inside that function?

+2  A: 

Try:

dostuff:  function() {
   var that = this;

   $$('.enabled').each( function(elem) {
        alert(that.bar);  //FTW
   });
}

Or, pass a context to each():

dostuff:  function() {
   $$('.enabled').each( function(elem) {
        alert(this.bar);  //FTW
   }, this); // Context
}
Ates Goral
A: 

Hmmm, I'm no Protoype expert, but I think this might help answer your question - http://www.duncangunn.me.uk/dasblog/2009/05/26/ObjectorientedEventHandlingInJavascript.aspx

Let me know if it does, if it doesn't, apologies for wasting your time!

Duncan
A: 

When you're inside the each(), this refers to what's being iterated with each. If there's only one instance of the class, replace all this's with Foo.

var Foo = Class.create({
bar : "bar",

  dostuff:  function() {
    $$('.enabled').each( function(elem) {
      alert(Foo.bar);  //FAIL
    });
  }
});

if you can't get away with alert(bar);

CrazyJugglerDrummer
+1  A: 

You can use Prototype's bind function, which 'locks [the function's] execution scope to an object'.

var Foo = Class.create({
  initialize:  function() {
    this.bar = 'bar';
  },

  dostuff:  function() {
    $$('.enabled').each( function(elem) {
      alert(this.bar);
    }.bind(this)); // Set the execution scope to Foo
  }
});
Zack Mulgrew
That does the trick. Thanks!
Mark Biek
bind() seems to be slightly an overkill since each() already takes a second parameter, which is the execution scope.
Ates Goral
Maybe Mark's original example isn't a good one then since it is a call to Enumerable.each which does allow you to specify scope. However, since the title of the question asks how to give *a function* access to class members I think Function.bind is more appropriate.
Zack Mulgrew
This example probably is a bit simple for bind() but I accepted this answer because I see bind() as having more long-term utility for me.
Mark Biek
A: 

Hi I have a javascript class like following:

Calendar = Class.create();
Object.extend(Calendar.prototype, {

refreshCalendar: function(k){ k = "z"; },

getButtonCode: function( k){
return "button class='button' onClick='oCalendar.refreshCalendar(\"" + k +"/button";
},

});//end of calendar class..

var oCalendar = new Calendar();//creating instance

//

This works fine as I have created an instance of calendar class, 'oCalendar'. Now is there any way so that I can access the method refreshCalendar in onClick event even if I dont create an instance of calendar class.

onClick='refreshCalendar(\"" + k +"/button"; or something similar that doesnt require calling the global instance oCalendar.

Thanks