Question

I'm trying to assign a callback dynamically to an Object of mine, I can't seem to figure out a way to do this while granting this function access to private variables. I've listed the relavant code below with comments where I ran into walls.

Object Factory

function makeObj ( o ) {
                function F() {}
                F.prototype = o;
                return new F();
            }

Module

var MODULE = (function(){
   var myMod = {},
       privateVar = "I'm private";
   return myMod;
})();

Various Attempts


myMod.someDynamicFunc = function someDynamicFunc(){
    //privateVar === undefined;
    alert( privateVar );
}
myMod.someDynamicFunc();

myMod.prototype.someDynamicFunc = function someDynamicFunc(){
    //ERROR: Cannot set property 'someDynamicFunc' of undefined
    alert(privateVar);
}
myMod.someDynamicFunc();

In this attempt I tried making a setter in the module object... to no avail.

var MODULE = (function(){
       var myMod = {},
           privateVar = "I'm private";

           myMod.setDynamicFunction = function ( func ){
              if(func !== undefined && typeof func === "function"){
                //Uncaught TypeError: 
                //         Cannot read property 'dynamicFunction' of undefined
                myMod.prototype.dynamicFunction = func;
                //also tried myMod.dynamicFunction = func;
              }
           }
       return myMod;
    })();

var myModule = makeObject( MODULE );

myModule.setDynamicFunction(function(){
   alert(privateVar);
});

myModule.dynamicFunction();

Am I just using JavaScript wrong? I'd really like to be able to assign callbacks after the object is initiated. Is this possible?

Was it helpful?

Solution

You can't access the private variable via a callback function set dynamically (since it can't be a closure if it's attached later), but you can set up a system by which you would be able to access the variable:

var MODULE = (function(){
   var myMod = {},
       privateVar = "I'm private";

   myMod.callback = function(fn) {fn(privateVar);};

   return myMod;
})();

var someDynamicFunc = function(param) {alert(param);};
myMod.callback(someDynamicFunc);

Of course, this makes it not really private, since anyone could do this. I don't see how it would be possible at all for you to have a "private" variable that you access via dynamically attached functions, without allowing anyone else's dynamically attached functions to have the same privilege (thus making it not really private).

OTHER TIPS

I guess you did not really understand exactly how closures work.

Closures mean that scopes always have access to the outer scope they were defined in.

function Counter(start) {
    var count = start;


    return {
        increment: function() { // has access to the outer scope
            count++;
        },

        get: function() {
            return count;
        }
    }
}

var foo = new Counter(4);
foo.increment();
foo.get(); // 5

The above example returns two closures, both the function increment as well as get keep a reference to the count variable defined in the constructor.

One cannot access count from the outside, the only way to interact with it is via the two "closured" functions.

Remember, closures work by keeping a reference to their outer scopes, so the following does not work:

var foo = new Counter(4);
foo.hack = function() { // is not getting defined in the same scope that the original count was
    count = 1337;
};

This will not change the variable count that's inside of Counter since foo.hack was not defined in that scope, instead, it will create or override the global variable count.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top