www.webdeveloper.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 35

Thread: [RESOLVED] How to share variables between innerFunction and closure scope?

  1. #1
    Join Date
    Jul 2010
    Posts
    135

    resolved [RESOLVED] How to share variables between innerFunction and closure scope?

    Hi, anybody can give me an advice?

    I had a original function in this format/syntax:

    Code:
    GlobalFunction(){
     InnerFunction(){
     // ... long definition here ...
     }
    
    if (condition)
    for (n in object)
     for (id in object[n])
      for (c in object[n][id])
        myInnerFunction();
    else
    if (condition)
    for (n in object)
     for (id in object[n])
        myInnerFunction();
    }
    Well, problem was that the innerFunction was initialized every time when I call it in loop! So I decided to use a closure, to make initialization only once:

    Code:
    GlobalFunction(){
     InnerFunction(){
     // ... long definition here ...
     }
    return function(){
     if (condition)
     for (n in object)
      for (id in object[n])
       for (c in object[n][id])
         InnerFunction(); // call inner function
     else
     if (condition)
     for (n in object)
      for (id in object[n])
         InnerFunction(); // call inner function
     } // end of closure
    }
    var myClosure=GlobalFunction();
    myClosure();
    Ok so this way, the innerFunciton is defined just once and saves time.
    But I realized I have two new problems when using closures this way. So I want to ask you what do you think about it.

    New solution means I need to declare new global variable: myClosure. That means that if I have more functions like 4 or 5 so this gets to the global scope. And then I see them in function context, in global scope of every function. I see all global variables + my global closures. This is contrary to the effort of reducing global variables and it produces a chaos in the scope. The more globals in function scope, the more chaos. Has it a sense to use closures? Here is another problem I met and that emphasize the essence what I've wrote now.

    The next problem is that with this use of closure, I need to pass variables to closure through arguments of it. According to example I use there n,id and c variable. In real, I use next 10 variables in the code I need to pass in. BUT NOW MY GREAT QUESTION: Is it really so, that I need to do it through arguments? Have I lost GlobalFunction inheritance ability? Now when I call myClosure I have to do it like so:

    Code:
    // code of closure:
    return function(){
     if (condition)
     for (n in object)
      for (id in object[n])
       for (c in object[n][id])
         InnerFunction(n,id,c,chain,i,... end so on ); // to get variables from closure to inside function. Too many arguments, too much work with debugging original code
     else
     if (condition)
     for (n in object)
      for (id in object[n])
         InnerFunction(n,id,c,chain,i,... end so on ); // to get variables from closure to inside function. 
     } // end of closure
    }
    Other words the innerFunction behaves like it is global and has not shared variables with myClosure! So what do you think, am I right or just I do some mistake in code?
    Last edited by crazy boy; 09-22-2010 at 06:57 AM.

  2. #2
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Quote Originally Posted by crazy boy View Post
    New solution means I need to declare new global variable: myClosure. That means that if I have more functions like 4 or 5 so this gets to the global scope. And then I see them in function context, in global scope of every function. I see all global variables + my global closures. This is contrary to the effort of reducing global variables and it produces a chaos in the scope. The more globals in function scope, the more chaos. Has it a sense to use closures? Here is another problem I met and that emphasize the essence what I've wrote now.
    While you do effectively increase the number of global variables by using a closure in this way, your inner functions are never exposed to the global scope. This means that if you have 4 or 5 functions contained within your global function, they will remain localized to that function -- they aren't exposed to the global object. You must create a minimum of 1 global object.

    Quote Originally Posted by crazy boy
    The next problem is that with this use of closure, I need to pass variables to closure through arguments of it.
    This is a little confusing. I think you're saying that the closure you're returning isn't able to inherit the variables in the scope of its parent function. However, that's false. Your closure may access variables local to the parent method indefinitely (even after the parent method has been deconstructed).

    Quote Originally Posted by crazy boy
    According to example I use there n,id and c variable. In real, I use next 10 variables in the code I need to pass in. BUT NOW MY GREAT QUESTION: Is it really so, that I need to do it through arguments? Have I lost GlobalFunction inheritance ability?
    You do not lose the ability to inherit variables, properties or methods of an ancestral scope. It is not necessary to pass these values as arguments to a closure; the closure will have access to the variables as a result of JavaScript's lexical scoping.

    Quote Originally Posted by crazy boy
    Code:
    // code of closure:
    return function(){
     if (condition)
     for (n in object)
      for (id in object[n])
       for (c in object[n][id])
         InnerFunction(n,id,c,chain,i,... end so on ); // to get variables from closure to inside function. Too many arguments, too much work with debugging original code
     else
     if (condition)
     for (n in object)
      for (id in object[n])
         InnerFunction(n,id,c,chain,i,... end so on ); // to get variables from closure to inside function. 
     } // end of closure
    }
    Other words the innerFunction behaves like it is global and has not shared variables with myClosure! So what do you think, am I right or just I do some mistake in code?
    It may make more sense to look into the apply() or call() methods to transmit a set of variables to another function in a way that scales indefinitely.

  3. #3
    Join Date
    Jul 2010
    Posts
    135
    Jona,
    thanks a lot for reply.

    While you do effectively increase the number of global variables by using a closure in this way, your inner functions are never exposed to the global scope. This means that if you have 4 or 5 functions contained within your global function, they will remain localized to that function -- they aren't exposed to the global object. You must create a minimum of 1 global object.
    For presence I leave the functions in global scope because it is more transparent for me. I have functions devided in three files and because the functions are long I had divided them and let'em in global. I think I could to move them later and do inner functions form them. But it will be less transparent having all in one file.


    Originally Posted by crazy boy
    "The next problem is that with this use of closure, I need to pass variables to closure through arguments of it."


    This is a little confusing. I think you're saying that the closure you're returning isn't able to inherit the variables in the scope of its parent function. However, that's false. Your closure may access variables local to the parent method indefinitely (even after the parent method has been deconstructed).

    Sorry that was mistake... I need to pass arguments to inner function. So I cannot access what is in closure from innerFucntion. I have to pass it through arguments...

    It may make more sense to look into the apply() or call() methods to transmit a set of variables to another function in a way that scales indefinitely.
    So I guess I have no other way then to call or apply innerFunction with arguments... Yes? I lost the ability of the first form which was without closure. The original form makes possible to use shared variables between closure and InnerFunction. The last form this doesn't support.

    So now I should do what?

    In fact I don't need to collect arguments of parent function. I'd preffer to have access to variables from closure
    Last edited by crazy boy; 09-22-2010 at 10:55 AM.

  4. #4
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Quote Originally Posted by crazy boy View Post
    For presence I leave the functions in global scope because it is more transparent for me. I have functions devided in three files and because the functions are long I had divided them and let'em in global. I think I could to move them later and do inner functions form them. But it will be less transparent having all in one file.
    If you have a series of functions that are attached to a common object or purpose, then you should wrap them in a pseudoclass, making your functions methods all within the scope of your one, global object function. This is not absolutely necessary, but it is recommended practice.


    Quote Originally Posted by crazy boy
    Sorry that was mistake... I need to pass arguments to inner function. So I cannot access what is in closure from innerFucntion. I have to pass it through arguments...
    By naming your inner function (a closure, of sorts, but not an anonymous function), you constrain its access to the scope. In this way, yes, you are limiting the inner function's access to variables.


    Quote Originally Posted by crazy boy
    So I guess I have no other way then to call or apply innerFunction with arguments... Yes? I lost the ability of the first form which was without closure. The original form makes possible to use shared variables between closure and InnerFunction. The last form this doesn't support.
    Given the pattern you chose, you don't have any other way to send that information to the inner function unless you define it in a scope common both to your closure and the inner function (meaning your global function must define the variables first). You could change this, but you would have to change the design of your program.

    Quote Originally Posted by crazy boy
    So now I should do what?

    In fact I don't need to collect arguments of parent function. I'd preffer to have access to variables from closure
    I have absolutely no idea what your goal is. I can answer your questions, but when you ask "what should I do?" the best answer I can give is based on the information you've given me, and in a lot of cases you're going to be simply making a design choice, which could often mean a trade-off between two benefits of competing design principles.

    If you want to access variables in your anonymous function, you can do so, but you must first define them in a scope ascendant to that function; this means either your global function or the global object itself.

  5. #5
    Join Date
    Jul 2010
    Posts
    135
    Jona,
    thanks a lot. I very appreciate this information and I will test it tomorrow.

  6. #6
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Not a problem. I'm happy to help. I feel I could help you a lot more if I had more specific questions, as yours seem very abstract (which naturally yields abstract and abstruse answers). I look forward to your further questions.

  7. #7
    Join Date
    Jul 2010
    Posts
    135
    Jona,
    I found something strange. I tried to simplify my code.

    Code:
    var myClosure = testFnc();  
    
    function testFnc(){
      function innerB(){
       return com+par;;
      }
      return function (){
      com=1; par="ok";
      console.log(
        innerB()
      );
      }
    };
    
    myClosure();
    result is "1ok".

    And now this is my problem. When I insert var com=1; in the closure instead com=1; so this is source of my problems.

    Code:
    function testFnc(){
      function innerB(){
      result = com+par;
       return result;
      }
      return function (){
      var com=1; par="ok";
      console.log(
        innerB()
      );
      }
    };
    error: "com is not defined".

    So whole the time I thought problem is in sharing variables, but now it looks like problem is in declaration of closure's variable... I don't understand why this happens. I thought var is necessary. Why it tells me I did not define com variable, when I did?

    Here is more specific problem in my code:

    Code:
    // THIS IS FROM WITHIN THE CLOSURE:
    for (n in vzory_)
       for (id in vzory_[n]){
        var i=0;
          for (c in vzory_[n][id]){
          vypisVzoryFnc.o[n][id]="";
          // vypisPrepData - is the inner function
          vypisPrepData(n,id,chainInfo(n,id),(i++),g);
         // call returns error "n is not defined", even if I use ... for (var n in ... 
    // or if I declare n in global function
          }
        }
    Of sure I am gonna remove the arguments for vypisPrepData()
    Last edited by crazy boy; 09-25-2010 at 03:35 AM.

  8. #8
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Hi,

    Using the
    var keyword restrict the declaration of the variable to the current function scope. When you omit it, it works because JavaScript assumes the variable should be within the global namespace rather than that of the current function scope. However, to be clear, you should be using var. The issue is where you've chosen to define your variable. Define it in the higher level function block in order for both your inner closure and your anonymous functions to both have permission to access it. I've modified your simplified example so you can see what I'm talking about below.

    Code:
    function testFnc(){
     var com, par;
      function innerB(){
      result = com+par;
       return result;
      }
      return function (){
      com=1; par="ok";
      console.log(
        innerB()
      );
      }
    };

  9. #9
    Join Date
    Jul 2010
    Posts
    135
    Quote Originally Posted by Jona View Post
    Hi,

    Using the
    var[font=arial] keyword restrict the declaration of the variable to the current function scope. When you omit it, it works because JavaScript assumes the variable should be within the global namespace rather than that of the current function scope.
    I realized I did test it only in FF. I did now test in IE without the var and no problem occurs. I don't want to use declaration in this case because it still seems to mee too complicated then I need to look for all variables from my closure which I would need to declare.

    however you did not answer about the last code of mine, where I try to use for .. in .. loop without declaration or with declaration in global function scope or with declaration in closure. All possibilities returns error "n" is not defined

    So what I want to do? I want a for loop in closure ... and get the vars to inner function. For (var n in object) .... get n to inner function without arguments.
    Last edited by crazy boy; 09-25-2010 at 01:37 PM.

  10. #10
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Quote Originally Posted by crazy boy View Post
    I realized I did test it only in FF. I did now test in IE without the var and no problem occurs. I don't want to use declaration in this case because it still seems to mee too complicated then I need to look for all variables from my closure which I would need to declare.
    Be aware that if your variable names aren't unique enough, you'll experience collisions and later on be rendered almost completely incapable of debugging your code for errors (the functionality kind, not syntax errors). When you can't figure out why it isn't working as expected, you'll need to check areas of your code such as these, where you don't make use of stricter scoping.

    Quote Originally Posted by crazy boy
    however you did not answer about the last code of mine, where I try to use for .. in .. loop without declaration or with declaration in global function scope or with declaration in closure. All possibilities returns error "n" is not defined

    So what I want to do? I want a for loop in closure ... and get the vars to inner function. For (var n in object) .... get n to inner function without arguments.
    You can't call another function and assume that the values of the parent block of code are definite unless that function definition occurs within the scope of the parent function block. You must use arguments, unless you want to define your inner function for every iteration of the loop (likely a bad practice).

  11. #11
    Join Date
    Jul 2010
    Posts
    135
    ...
    Last edited by crazy boy; 09-25-2010 at 03:56 PM. Reason: delete

  12. #12
    Join Date
    Jul 2010
    Posts
    135
    OK, resolved so far.

    Code:
    function vypisVzoryFnc(){
      var n,id,c,i,chain; // I DECLARED WHAT GOES IN INNER FNC.
    
      function chainInfo(n,id){
      }
    
      function vypisPrepData(){
         if (vzory_[n][id]["root"]) {} 
      }
    
    /*************
     ** CLOSURE ** -> vypisVzoryClosure()
     *************/
    
    return function(){
      for (n in vzory_)
       for (id in vzory_[n]){
          i=0;
          for (c in vzory_[n][id]){
          i++;
          chain = chainInfo(n,id);
          vypisVzoryFnc.o[n][id]="";
          vypisPrepData();
          }
        }
    
    } // end of cosure
    }
    I had to repair "for (var n in object)" to "for (n in object)"
    Last edited by crazy boy; 09-25-2010 at 04:48 PM.

  13. #13
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Is there any reason you're returning a function, rather than processing it immediately? Is your goal to dispose the object but make its instance persistent?

  14. #14
    Join Date
    Jul 2010
    Posts
    135
    Code:
    var vypisClosure=vypisVzoryFnc();
    vypisClosure is called on every click on form element like select or input. The goal is to initialize inner functions once, not on every click.

  15. #15
    Join Date
    Jan 2003
    Location
    Texas
    Posts
    10,413
    Quote Originally Posted by crazy boy View Post
    Code:
    var vypisClosure=vypisVzoryFnc();
    vypisClosure is called on every click on form element like select or input. The goal is to initialize inner functions once, not on every click.
    That makes sense, but wouldn't it make more sense to store your functions library externally in some global object and reference those methods through that one global namespace?

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center



Recent Articles