views:

203

answers:

3

A simplified example:

// Let's create a new object
function MyObject() {
    //
}

// Add some method to this object
MyObject.prototype.myFunctionA = function() {
    //
}

// Another method
MyObject.prototype.myFunctionB = function(arg) {
    // AJAX GET request          
    $.get('script.php', { par : arg }, function(data) {

        // and here in the callback function    
        // I need to call MyObject.prototype.myFunctionA method!
        // but "this" references callback function so
        // I don't know how to access MyObject here

    });
}

I have explained my issue in the comments. How can I do that?

+4  A: 

you can assign "var self = this" in MyObject.prototype.myFunctionB before calling the $.get then you can use the alias "self" inside the callback.

MyObject.prototype.myFunctionB = function(arg) {
    var self = this;

    $.get('script.php', { par : arg }, function(data) {
       alert(self);
    });
}
gpilotino
Clean and simple. Great answer!
Doug Neiner
+4  A: 

simplest:

// Let's create a new object
function MyObject() {
    //
}

// Add some method to this object
MyObject.prototype.myFunctionA = function() {
    //
}

// Another method
MyObject.prototype.myFunctionB = function(arg) {
    // AJAX GET request       
    var me = this;   
    $.get('script.php', { par : arg }, function(data) {
        // use me.something instead of this.something
    });
}

reusable (using scope trapping):

function createDelegate(obj, handler)
{
    return function() {
        handler.apply(obj, arguments);
    }
}

then

MyObject.prototype.myFunctionB = function(arg) {
    // AJAX GET request       
    var me = this;   
    $.get(
        'script.php', 
        { par : arg },
        createDelegate(this, function(data) {
        // use this.something
        })
    );
}

So, some code in relation to the comments below, createDelegate can also be used in a few different ways, one of which being:

function createDelegate(obj, handler)
{
    handler = handler || this;
    return function() {
        handler.apply(obj, arguments);
    }
}

Function.prototype.createDelegate = createDelegate;

this allows you to do things like:

var someObj = {a:1, b:function() {return this.a;}};
var scopedDelegateForCallback = someObj.b.createDelegate(whateverobj)

you can do tricks to get parent too, but that's too much for me to bother with atm.

or, you can do something like this:

function createDelegate(handler, obj)
{
    obj = obj || this;
    return function() {
        handler.apply(obj, arguments);
    }
}

Object.prototype.createDelegate = createDelegate;

and to use it:

someObj.createDelegate(someObj.b);

or maybe:

function createDelegateForMember(handlerName, obj)
{
    obj = obj || this;
    return function() {
        obj[handlerName].apply(obj, arguments);
    }
}

Object.prototype.createDelegate = createDelegateForMember;

then

someobj.createDelegate("b");
Luke Schafer
I like your `createDelegate` function, but I think it'd be even better if you moved the `obj` parameter to the end of the parameter list and made it optional, defaulting to `this`. That would save some code in the most common use-case.
bcat
if you're not specifying 'this', it's useless to use the createDelegate function :)
Luke Schafer
No, I meant something like this: `function createDelegate(handler, obj) { return function () { handler.apply(obj || this, arguments); }; }`.And calling it like this: `$.get('script.php', { par: arg }, createDelegate(function (data) { /* do something */ }));`.
bcat
yeah, but 'this' in 'obj || this' refers to the 'this' of the function returned by createDelegate, which will be set to 'window' (as, for that matter, will the 'this' for createDelegate) - TBC for readability
Luke Schafer
i was going to post another comment, but will put it in my post, give me a minute :)
Luke Schafer
Oh! You're right, of course. My bad.
bcat
no probs. Added some alternatives above
Luke Schafer
Wow, what a post! +1
Pekka
+3  A: 

JavaScript functions "close over" variables in outer scopes, so you can do this:

// Another method
MyObject.prototype.myFunctionB = function(arg) {
    // Save `this` reference for use in callback.
    var that = this;

    // AJAX GET request
    $.get('script.php', { par : arg }, function(data) {

        // Now `that` holds the contents of the current `MyObject`.
        // So you can call other methods.
        that.myFunctionA();
        // ... etc ...

    });
}
bcat
+1 for link to closure explaination
Luke Schafer