can an actionscript function find out its own name?
Asked Answered
U

7

12

given the following

function A(b:Function)   { }

If function A(), can we determine the name of the function being passed in as parameter 'b' ? Does the answer differ for AS2 and AS3 ?

Unlikely answered 2/4, 2009 at 20:9 Comment(0)
Z
15

I use the following:

private function getFunctionName(e:Error):String {
    var stackTrace:String = e.getStackTrace();     // entire stack trace
    var startIndex:int = stackTrace.indexOf("at ");// start of first line
    var endIndex:int = stackTrace.indexOf("()");   // end of function name
    return stackTrace.substring(startIndex + 3, endIndex);
}

Usage:

private function on_applicationComplete(event:FlexEvent):void {
    trace(getFunctionName(new Error());
}

Output: FlexAppName/on_applicationComplete()

More information about the technique can be found at Alex's site:

http://blogs.adobe.com/aharui/2007/10/debugging_tricks.html

Zebedee answered 3/4, 2009 at 14:14 Comment(4)
I would say be careful using this in your system design, it is pretty brittle code, as in, if someone at Adobe decides to rephrase their stack trace message your code breaks. So maybe ask yourself if you really need to know the functions name to solve the problem you have.Ron
Agreed. I use it primarily for debugging, and not so much lately since I can step through code with Flex Builder Pro.Zebedee
very cool idea ... but works only in debug player!!! if that is sufficient, ok, but in general this still does not solve the problem ....Cowardice
With Air 3.5 & Flash 11.5 it is now possible to get a stack trace with release builds. I agree that this method is risky - a small change in the stack trace string format could easily break code, but it works, and works well.Elswick
B
6

I've been trying out the suggested solutions, but I ran into trouble with all of them at certain points. Mostly because of the limitations to either fixed or dynamic members. I've done some work and combined both approaches. Mind you, it works only for publicly visible members - in all other cases null is returned.

    /**
     * Returns the name of a function. The function must be <b>publicly</b> visible,
     * otherwise nothing will be found and <code>null</code> returned.</br>Namespaces like
     * <code>internal</code>, <code>protected</code>, <code>private</code>, etc. cannot
     * be accessed by this method.
     * 
     * @param f The function you want to get the name of.
     * 
     * @return  The name of the function or <code>null</code> if no match was found.</br>
     *          In that case it is likely that the function is declared 
     *          in the <code>private</code> namespace.
     **/
    public static function getFunctionName(f:Function):String
    {
        // get the object that contains the function (this of f)
        var t:Object = getSavedThis(f); 

        // get all methods contained
        var methods:XMLList = describeType(t)..method.@name;

        for each (var m:String in methods)
        {
            // return the method name if the thisObject of f (t) 
            // has a property by that name 
            // that is not null (null = doesn't exist) and 
            // is strictly equal to the function we search the name of
            if (t.hasOwnProperty(m) && t[m] != null && t[m] === f) return m;            
        }
        // if we arrive here, we haven't found anything... 
        // maybe the function is declared in the private namespace?
        return null;                                        
    }
Broglie answered 20/7, 2011 at 16:4 Comment(2)
Good approach, but getSavedThis() works only in debug versions of flash player.Formalin
Thanks for this, and in case anyone else has trouble finding the packages: import flash.utils.describeType; import flash.sampler.getSavedThis;Tidings
G
3

Heres a simple implementation

    public function testFunction():void {
        trace("this function name is " + FunctionUtils.getName()); //will output testFunction
    }

And in a file called FunctionUtils I put this...

    /** Gets the name of the function which is calling */
    public static function getName():String {
        var error:Error = new Error();
        var stackTrace:String = error.getStackTrace();     // entire stack trace
        var startIndex:int = stackTrace.indexOf("at ", stackTrace.indexOf("at ") + 1); //start of second line
        var endIndex:int = stackTrace.indexOf("()", startIndex);   // end of function name

        var lastLine:String = stackTrace.substring(startIndex + 3, endIndex);
        var functionSeperatorIndex:int = lastLine.indexOf('/');

        var functionName:String = lastLine.substring(functionSeperatorIndex + 1, lastLine.length);

        return functionName;
    }
Geophyte answered 12/7, 2011 at 23:51 Comment(0)
R
2

The name? No, you can't. What you can do however is test the reference. Something like this:

function foo()
{
}

function bar()
{
}

function a(b : Function)
{
   if( b == foo )
   {
       // b is the foo function.
   }
   else
   if( b == bar )
   {
       // b is the bar function.
   }
}
Rollandrollaway answered 2/4, 2009 at 22:10 Comment(0)
I
0

Are you merely looking for a reference so that you may call the function again after? If so, try setting the function to a variable as a reference. var lastFunction:Function;

var func:Function = function test():void
{
    trace('func has ran');
}

function A(pFunc):void
{
    pFunc();
    lastFunction = pFunc;
}
A(func);

Now if you need to reference the last function ran, you can do so merely through calling lastFunction.

I am not sure exactly what you are trying to do, but perhaps this can help.

Intervale answered 3/4, 2009 at 1:9 Comment(0)
T
0

I don't know if it helps, but can get a reference to the caller of the function which arguments (as far as I know just in ActionScript 3).

Tablet answered 6/4, 2009 at 11:9 Comment(1)
You can't get the caller, but you do have a reference to the callee.Turnabout
M
0

Use arguments.callee with toString() and match in general:

function foo(){return arguments.callee.toString().match(/\s\w+/).toString()}

References

Midmost answered 11/9, 2014 at 19:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.