views:

67

answers:

4

This is a very old problem, but I cannot seem to get my head around the other solutions presented here.

I have an object

function ObjA() {
    var a = 1;
    this.methodA = function() {
        alert(a);
    }
}

which is instantiated like

var myObjA = new ObjA();

Later on, I assign my methodA as a handler function in an external Javascript Framework, which invokes it using the apply(...) method.

When the external framework executes my methodA, this belongs to the framework function invoking my method.

Since I cannot change how my method is called, how do I regain access to the private variable a?

My research tells me, that closures might be what I'm looking for.

+1  A: 

yes, you're right. Instead of a method reference

 var myObjA = new ObjA();

 libraryCallback = myObjA.methodA

pass a closure

 libraryCallback = function() { myObjA.methodA() }
stereofrog
+2  A: 

You already have a closure. When methodA is called the access to a will work fine.

Object properties are a different thing to scopes. You're using scopes to implement something that behaves a bit like ‘private members’ in other languages, but a is a local variable in the parent scope, and not a member of myObjA (private or otherwise). Having a function like methodA retain access to the variables in its parent scope is what a ‘closure’ means.

Which scopes you can access is fixed: you can always access variables in your parent scopes however you're called back, and you can't call a function with different scopes to those it had when it was defined.

Since a is not a property of this, it doesn't matter that this is not preserved when calling you back. If you do need to get the correct this then yes, you will need some more work, either using another closure over myObjA itself:

onclick= function() { myObjA.methodA(); };

or using Function#bind:

onclick= myObjA.methodA.bind(myObjA);
bobince
You are right. I really do have access to `a`, but I cannot verify this using Firebug. But thanks a lot for enlighting me!
Chau
You can see parent scopes and their variables in Firebug by looking inside the `scopeChain` pseudo-variable in the ‘Watch’ tab.
bobince
Yes yes, I know. But these variables does not appear in my firebug. I cannot access them in the console either - though it does not response as if they were undefined, just no response.
Chau
A: 

If you are using jQuery javascript framework, easiest way is to use proxy:

$('a').click($.proxy(myObjA, 'methodA'));
Juraj Blahunka
I am not using jQuery.
Chau
A: 

I'd do this:

function ObjA() {
    this.a = 1;
    this.methodA = function() {
        alert(this.a);
    }
}

function bindMethod(f, o) {
    return function(){
        return f.apply(o, arguments);
    }
}

var myObjA = new ObjA();
myObjA.methodA = bindMethod(myObjA.methodA, myObjA);
...

Where bindMethod binds the methodA method to always be a method of myObjA while still passing on any arguments which function() {myObjA.methodA()} doesn't do.

David Morrissey