Archive for February, 2007

A Better Way To Determine a Function’s Caller

There are some rare instances, mainly during debugging, where you may need to determine which function called the current function. For example, you may have a function that is repeatedly called at many places in your code, and you need to determine which function calls it at a specific time.

ActionScript provides arguments.caller for this. However, using arguments.caller returns only a reference to the caller function, and leaves out details such as its name, type, etc. Take a look at this example:

function test(){
	trace("this function was called by " + arguments.caller);
}
function callTest(){
	test();
}
callTest();

The output of this is:

this function was called by [type Function]

Um, thanks, I guess.

My function was called by a function. This is about as helpful as [Object object] or, my personal favorite, “undefined is not defined.”

The trace output is giving us a [type Function] because it’s the only way Flash can trace a reference. The way around this is to check the reference against everything and test for equality. Let’s add a new function to the above code:

function getCaller(callerObj){
	var str:String = callerObj + newline + "";
	for(i in _root){
		if(callerObj == _root[i]) {
			return i.toString();
		}
	}
}

function test(){
	trace("this function was called by " + getCaller(arguments.caller));
}
function callTest(){
	test();
}
callTest();

The output has changed for the better:

this function was called by callTest

Presto! You’ve gotten your caller function’s name. The getCaller function is looping through everything in _root. When the loop encounters a function, it is really encountering a reference to that function, just like arguments.caller is a reference to the caller function. Therefore, the if statement is comparing references to references and is able to accurately determine whether the caller property passed to it is the same as an existing function, and then return its name (or, more accurately, the name of the index of that reference in the _root object) as a string.

Please keep in mind, however….

This method is not perfect. I’ll admit it. It only works for functions that are defined on a frame in the main timeline. It won’t work for anonymous (inline) functions, calls made from a nested object such as a movie clip, component, or class, or outside calls coming in from JavaScript or any other external interface.

None of these flaws are unfixable, and time permitting, I’ll work on ways to improve this method, but the basic concept of this code (comparing references) will remain the same.

,

1 Comment