3
function LolClass(){

    this.init = function(){             
        button_a.bind("tap", function(){                
            this.refreshFields(); // doesn't work 
            //refreshFields(); // doesn't work either
        });     
    }

    this.refreshFields = function(){
        alert("LOL");
    }

    this.dummy = function(){
        this.refreshFields(); // W O R K S!
    }
}

When I tap the button_a, I get a reference error, as refreshFields method isn't "found".

Uncaught ReferenceError: refreshFields is not defined at file:///android_asset/www/src/pages/main.js:70

But if I call that method in other places than that tap listener, it works.

I'm totally certain that the this inside the tap listener function is referencing to button_a, the event target.

My question is: What is the best(oo) fix for that?

Marcelo Assis
  • 4,940
  • 3
  • 31
  • 53
  • I think `this` is referring to `button_a`, so it's not in the right scope. I'm not entirely sure but you might have to pass the parent object into the function to reference it inside. – sachleen Jun 12 '12 at 17:55
  • What is `.bind()`? Is it part of some library? If so, does that `.bind()` method accept a `context` argument? –  Jun 12 '12 at 18:04
  • 1
    Note that this pattern in javascript is deprecated. If you forget the `new` operator, very bad things can happen. you should use `closure`. – gdoron is supporting Monica Jun 12 '12 at 18:05
  • @gdoron, can you provide me links related to that deprecation? – Marcelo Assis Jun 12 '12 at 18:20
  • 1
    @MarceloAssis. A book - [JavaScript: The Good Parts](http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742) – gdoron is supporting Monica Jun 12 '12 at 18:23
  • Just to be sure, @amnotiam. my comment above is right, right...? – gdoron is supporting Monica Jun 12 '12 at 18:25
  • @amnotiam, it's from JQuery. It's just another way of adding an event listener. – Marcelo Assis Jun 12 '12 at 18:27
  • @gdoron: If you mean the creation of objects via `new`, then I've got to disagree with you on that one. But then I disagree with lots of Crockford stuff. –  Jun 12 '12 at 18:34
  • @MarceloAssis: Alright, yeah jQuery's `.bind()` doesn't offer any way to override the calling context. It does however let you pass event data, which you could use instead of the `self` variable. –  Jun 12 '12 at 18:36
  • @amnotiam. Don't you think a missing `new` is risky? Why won't you use `closures`? I'm feel safe with Crockford behind me... :) – gdoron is supporting Monica Jun 12 '12 at 18:37
  • @gdoron: By closures, do you mean "functional inheritance", or something else? Either way, I think any misuse of an API is risky. The solution is usually to use the API properly. I will say that a nice pattern is to make a function that calls the constructor with `new` on your behalf, much like jQuery does. I've heard lots of Crockford advice that I entirely disagree with. –  Jun 12 '12 at 18:40

3 Answers3

8

Try this

function LolClass(){

    var someVar = 0; 
    var self = this;

    this.init = function(){             
        button_a.bind("tap", function(){                
            self.refreshFields(); // now works!
            //refreshFields(); // doesn't work
        });     
    }

    this.refreshFields = function(){
        alert("LOL");
    }

    this.dummy = function(){
        this.refreshFields(); // W O R K S!
    }
}
Marcelo Assis
  • 4,940
  • 3
  • 31
  • 53
Trinh Hoang Nhu
  • 11,854
  • 5
  • 53
  • 79
4

You should cache this:

var that = this; // "that" is a convention name for "this"
this.init = function(){             
        button_a.bind("tap", function(){                
            that.refreshFields(); 
        });     
    }
gdoron is supporting Monica
  • 136,782
  • 49
  • 273
  • 342
4

You need to modify your code:

function LolClass(){

    var someVar = 0; 
    var $this = this;

    this.init = function(){             
        button_a.bind("tap", function(){                
            $this.refreshFields();
        });     
    }

    this.refreshFields = function(){
        alert("LOL");
    }

    this.dummy = function(){
        this.refreshFields(); // W O R K S!
    }
}

"this" inside callback refers to different object. I added var $this = this; and used $this inside callback.

ioseb
  • 15,719
  • 2
  • 30
  • 28