views:

261

answers:

5

Sorry if this has been answered, but I couldn't turn up a search for it... a difficult thing to search for, I think!

Say I have this:

var MyPrototype = function() { this.init(); }
$.extend(MyPrototype.prototype, {
    a: 5,
    init: function() {
        var thing = new SomeOtherClass();
        thing.meth = this.meth;
        // thing.meth() is called somewhere within thing;
    },
    meth: function() {
        alert(this.a);
    }
}

Basically, I am dealing with another class which uses its own methods as callbacks, e.g. I am expected to override them with my own functionality. But I need to retain the proper scope of this while doing it (the only thing I care about from SomeOtherClass is what's passed to the callback; nothing in the state).

As you might imagine, this doesn't work because thing has no a property! I am not familiar enough with the intricacies of Javascript scoping to know how to make this refer to what I want, though!

A: 

How about:

thing.meth.call(this);

or

thing.meth.apply(this);

(The only difference is in how arguments are passed, which doesn't matter in this case.)

Tim Sylvester
Unfortunately, as they are callbacks initiated from `SomeOtherClass`, I don't actually control how they are called.
tdavis
In that case, you just need to wrap the callback in a closure so the value of "this" is carried along with the function reference. *edsoverflow* already posted an example.
Tim Sylvester
A: 

Could you do something like this?

var MyPrototype = function() { this.init(); }
$.extend(MyPrototype.prototype, {
    a: 5,
    init: function() {
        var thing = new SomeOtherClass();
        var self = this;
        thing.meth = function(){this.meth.apply(self)};
        // thing.meth() is called somewhere within thing;
    },
    meth: function() {
        alert(this.a);
    }
}
agilefall
Your "this" within the "helper" method that calls "meth" still has the same problem that it originally had.
Chris Pietschmann
Changed it to use self. Works ok for me now.
agilefall
+1  A: 

Since you can't control how it's called you could try this:

var MyPrototype = function() { this.init(); }
$.extend(MyPrototype.prototype, {
    a: 5,
    init: function() {
        var thing = new SomeOtherClass();

        // Create an aliad for this
        var that = this;
        thing.meth = function() {
            // You can always access the object using it's "that" alias
            alert(that.a);
        };
    }
}

Or...

var MyPrototype = function() { this.init(); }
$.extend(MyPrototype.prototype, {
    a: 5,
    init: function() {
        var thing = new SomeOtherClass();

        // Create an aliad for this
        var that = this;
        thing.meth = function() {
            // You can always access the object using it's "that" alias
            that.meth();
        };
    },
    meth: {
        alert(this.a);
    }
}
Chris Pietschmann
+2  A: 

Combining two other answers here, so that you don't have to rewrite your meth function, I'd do this:

    var me = this;
    thing.meth = function() {
        MyPrototype.meth.apply(me, arguments);
    };
edsoverflow
A: 

Before the start of your code sample, add this line:

var self = this;

Then replace all uses of 'this' in your code with 'self'.

(I think a bunch of the answers to this are saying more or less the same thing.)

aem