Link to home
Start Free TrialLog in
Avatar of walkman69
walkman69

asked on

Variable passing in anonymous functions

I'm a bit confused..

It is possible to do:

function setVariable(func) {
        func['variable'] = 'foobar';
}

function a () {
        setVariable(this);
        console.log(this.variable);   // "foobar"
}

Open in new window


------

But not this?


var initFunctions=[function()  {
        console.log(this.variable);   // "undefined"  
}];

for(x = 0; x < initFunctions.length; x++) {
        initFunctions[x]["variable"] = "foobar";
        initFunctions[x]();  // Run function
}




// Why da fork does the second one become undefined?
// What do I miss? I know I can return the variable value as an argument instead like:

var initFunctions=[function(returnedValue)  {
        console.log(returnedValue);   // "foobar"  
}];

for(x = 0; x < initFunctions.length; x++) {
        initFunctions[x]("foobar");  // Run function
}

Open in new window


But that's not as neat as declaring variables on the run...
help?....
Avatar of walkman69
walkman69

ASKER

um.. Its since it hasn't become an own instance yet?.. right?
Then this is impossible to do for anonymous functions?
ASKER CERTIFIED SOLUTION
Avatar of Rob
Rob
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Remember that all javascript elements are objects and some more simple than others.  A function is just a basic class with itself as the constructor.
Some extensions on the basic function when you think of it as an object rather than a standalone function:
http://jsbin.com/loves/1/edit
var func = function a(myname) {
    this.name = myname;
    var name2 = myname + "_more";

    function b() {
        console.log("B");
    }
    this.c = function() {
        console.log("C");
        b();
    };
    this.getName = function(){
        console.log(this.name);
    };
    this.getName2 = function() {
        console.log(name2);
    };
    this.getStatic = function(varName) {
        console.log(func[varName]);
    };
};

// create an instance of the class so internal members are accessible
var myvar = new func("rob");
myvar.getName();              // "rob"
myvar.name = "not rob";
myvar.getName();              // "not rob" as name is public
console.log(myvar.name2);     // "undefined" as name2 is private
myvar.getName2();             // "rob_more"
//myvar.b();                  // throws an error and halts execution! as b() is private
myvar.c();                    // "C" AND "B" as can access the private function b()

func.variable = "rob2";
console.log(func.variable);   // "rob2" as it is statically set on the object
console.log(myvar.variable);  // "undefined" to show the instance cannot access a static member externally
console.log(myvar.getStatic("variable")); // "undefined" to show that the instance cannot access the object variable from inside the object.  This would make no sense as the class would never know about the external assignment

Open in new window

Did what I post make sense?  If not, ask away as it's not the easiest of topics to get your head around.
I'm sorry for not responding earlier. I didn't think someone would respond to the question..
It makes perfect sense.. I know about private/public scope in Javascript. There were some uncertainties that I had in my knowledge of the inner workings of javascript.. I think you cleared the last piece of the puzzle..

If I explain my whole situation, it's for a piece of code launched after an ajax-call.

After posting here I wrote it to look something like this:
Note that because I have a similair piece of code written in 10 000 rows of code here and there (but Without the declaration of the anonymous function directly IN callAjax arguments.. But as separate instantiated global functions.) I had to add some code to the ending of the argument list, so that I don't need to rewrite 10 000 rows of code..
I will do however.. but not right now.. I'm in a bit of a hurry.. ;)

Anyways It looks somewhat like this now:


var someOutsideVariable = "The GNU Is an almighty and powerful creature..";

var params = 'url=' + '../somedirectory/foo.bar' + '&data=' + data + '&id=' + g.user_id + '&ver_str=' + g.user_ver_str; // The last parameters is only to make sure the right user loads the file and noone else.
                                                
callAjax(
      method='POST',
       url=g.urlroot + g.extraSubDir + '/login/php_includes/proxy_put_file.php',
       params=params,
      async=true,
       getResponse=true,  // This posts the responseText in namespace g.responseText
      namespace=g,
       initFunctions=[function(responseText, args){
            
            // And here goes the code..
            console.log(args.someOutsideVariable);   // Story about GNU appears..
            console.log(responseText);   // Shows responseText
            
}], elem='', errorReport=false, args={
      'someOutsideVariable' : someOutsideVariable,
       'eventualOtherVariable' : eventuallyOtherVariable;
}
);            
                                                

When the callAjax-function has loaded the file, it falls back to calling
initFunctions like this:

function initFunctionsLoader(responseText, args) {      
       if (initFunctions.length > 0) {
             for(x = 0; x < initFunctions.length; x++) {
                   initFunctions[x](responseText, args);
             }
       }
}



I had to renew atleast a piece of the code since it's storage of responseText in
g.responseText is unresponsibe since it can easily be overwritten by a simultaneus callAjax() and then the result is something totally different.  But up until now, I only used callAjax() with .async = false; Don't even ask me why.. I've been under a lot of stress.. But so far it worked.. Now I want to start making more use of asynchronization and that's why I needed both passing of functions as well as arguments. And I find coding with anonymous functions more appealing than instantiations.. But I don't really like having to send the arguments each time with the "args"-argument list. This quickly gets booring when nestling the init-functions with another callAjax()-call with more initFunctions.. That is.. If I need for example the same variable in every function.
Ok, you may probably suggest the passing around a common namespace or something here.. And perhaps that's one way to go.. I'm just curious what way would be the best..

I liked your explanations..
*laughing* I read your previous comment saying to myself "he really should use a namespace here to prevent variables from being accidently overriden"... !  So that should answer your question.

If it's not your variable then you have to be careful as javascript does everything by reference

take the following code:
var a = {};
var b = a;

a.name = "a";
a.value1 = 10;
b.name = "b";

console.log(a);  // [Object] name: "b", value1: 10
console.log(b); // [Object] name: "b", value1: 10

Open in new window


Both objects will spit out the same values to the console. see the comments in the code above.
To get around this you need to copy the object, value by value.

I mentioned this because you set g=namespace and if g.user_ver_str is not your namespace, (could be google's?) then any changes you make to g will be reflected in namespace and vice versa.

I've written an article on this as it spurred my interest :)
http:A_13138-Javascript-is-just-an-Object.html

It sounds to me though that you're on the right track with all of this.  Anything in particular you'd like me to clarify?
Did my last post answer your questions? Did the article help?
Happy to continue the discussion :-)
Oh.. nice.. I'm happy I can spurr you..
I read it.. sweet article =)

yea.. g is my namespace.. don't wear it out ;)
Funny story though ^^

I think i'm all good for now..
My understanding has increased somewhat. And i'm more sure
that the path i'm about to embarc uppon is perhaps more accurate
in terms of javascript "perfection".. than it has been earlier..

Of course one could ask if asynchronous mode is always the best option.
And most people would probably say that it is.. However I think that
there are moments where no other activity is running where one can take the time
to run something and expect a result back without delay..

But I think i'll stick to async for a while now and throw in some of thoose
peachy namespaces.. It will be awesum.. ;)

Thanks Rob!

// Walkman69
Your help was deeply appreciated and your comments were exeptionally thorough.. thanx!