5 Replies Latest reply on Mar 15, 2011 8:06 PM by newbie_dev

    AS3 - function passed as argument has wrong scope when invoked

    newbie_dev Level 1

      Hi all,

       

      I am new to flex. I have been trying to this : http://seancode.blogspot.com/2008/07/flex-injection-passing-function-to.html

       

      This post basically has a component MyBox which gets a function as an argument and calls the function on a button click.

      It has another component Main which has defined a function func and has MyBox as a child and gives the function to MyBox.

       

      The problem is : func accesses properties of Main. So when it gets invoked it is supposed to run in Main's scope but in my application it is running in MyBox's scope and giving a Reference Error of property not found.

       

      I have read that in AS2, mx.utils.Delegate was used to specify the scope in which a function should execute. This was used to set event listeners. And AS3 is supposed to do this automatically - magic/method closures. I have had no issues setting event listeners and they run in the correct scope..

       

      Please tell me where I am going wrong.. there is no Delegate to work around this issue now. And I couldnt find anyone else facing this issue in AS3.

       

      thanks in advance..

        • 1. Re: AS3 - function passed as argument has wrong scope when invoked
          bmleite

          Hi,

           

          The problem is that you are using an inline function instead of a bound method. In this case, when you use an inline function, the scope of that function will be the scope of the caller (following the example the caller will be the MyBox component) and not the scope of the creator (Main). You can find more info on Function scopes here: http://livedocs.adobe.com/flex/3/html/help.html?content=03_Language_and_Syntax_21.html

           

          If you don't need the Bindable part, you can circumvent the problem by using a bound method/function:

          (using the same example you provided)

           

          private function backToViewZero():void {
               viewStack.selectedChild = viewZero
          }
          

           

          Another way (without discarding the Binding mechanism) is to use the call method of the function and specify the thisArg as being the parent (Main).

           

          <mx:Button label="Back" click="{ _buttonClick.call(parent) }"/>

          • 2. Re: AS3 - function passed as argument has wrong scope when invoked
            newbie_dev Level 1

            Hey thanks for the help. I tried out both of these... dint work

             

            1. removed the part - kept the function backToViewZero private - gave the same error

            2. removed the part - made the function public - still the same error

            3. removed the part - replaced _buttonClick() with _buttonClick.call(parent) - error saying that "viewstack" doesn’t exist on mx.container.ViewStack

            4. removed the part - replaced _buttonClick() with _buttonClick.call(parentApplication) - worked fine

            5. using parent or parentApplication - the result doesnt change if I keep the tag or keep the function private

             

            I cant use parent/parentApplication because my requirement is that this function should work if called from anywhere. And from what I have read, it should work but for some reason it is not working for me.

             

            Don’t know if this info is useful but - Im using AS3, Flex sdk 4.0 and Flash builder. The application is running in firefox with debugger version of Flash player - plugin WIN 10,2,152,26

            • 3. Re: AS3 - function passed as argument has wrong scope when invoked
              bmleite Level 1

              When you say:

               

              1. removed the Bindable part - kept the function backToViewZero private - gave the same error

               

              Do you mean that you kept the code like this? (option 1)

               

              [Bindable]
              private var backToViewZero:Function = function():void {
                  viewStack.selectedChild = viewZero;
              };     
              
              

               

              Or have you changed to this? (option 2)

               

              private function backToViewZero():void {
                  viewStack.selectedChild = viewZero;
              }
              

               

              The first option will not work, you cannot use the backToViewZero as a variable, you have to switch to a bound function (second option).

               

              Let me know if this helps.

              • 4. Re: AS3 - function passed as argument has wrong scope when invoked
                newbie_dev Level 1

                Oh shoot! I kept it as

                 

                private var backToViewZero:Function = function():void {

                    viewStack.selectedChild = viewZero;

                };    

                 

                No Bindable tag.

                 

                It is working after making it as option 2!!

                 

                Thank you sooo much

                • 5. Re: AS3 - function passed as argument has wrong scope when invoked
                  newbie_dev Level 1

                  You know what!

                   

                  The following  works fine :

                   

                  private function backToViewZero():void {

                      viewStack.selectedChild = viewZero;

                  }


                  [Bindable] public funcPar : Function = backToViewZero;

                  <components:MyBox id="viewOne" labelText="One" buttonClick="{this.funcPar}" />

                   

                  Now, I can actually change funcPar to point to some other function at run time and it still works fine!!!