2011-01-19 3 views

ответ

26

Используйте arguments.callee, чтобы получить ссылку на текущую функцию.

Я хочу получить имя функции, это немного сложнее: все функции рассматриваются как закрытие методов (фрагменты кода, которые могут передаваться как аргумент), поэтому они не имеют ссылки на прилагаемый тип класса, и у них нет «текущего имени».

Однако, если (и только если) метод является общедоступным, и вы хотите, чтобы получить имя метода из класса декларации объекта экземпляра, содержащего метод, вы можете использовать describeType:

public function someFunction() : void { 
    var callee:Function = arguments.callee; 
    trace (getFunctionName(callee, this)); // ==> someFunction 
} 

private function someOtherFunction() : void { 
    var callee:Function = arguments.callee; 
    trace (getFunctionName(callee, this)); // ==> not found 
} 

private function getFunctionName (callee:Function, parent:Object):String { 
    for each (var m:XML in describeType(parent)..method) { 
     if (parent[[email protected]] == callee) return [email protected]; 
    } 
    return "not found"; 
} 

Обратите внимание, что это не сработает, если вы вызываете someFunction() из конструктора, потому что объект не полностью создан - describeType(this) в конструкторе вызовет ошибку компиляции.

+1

Быстрое примечание: если вы хотите использовать это из другого класса, вы должны заменить 'this [m. @ Name]' на 'parent [m. @ Name]' –

+0

. Это была ошибка. Спасибо, что привлекли его к себе, @kriswelsh – weltraumpirat

2

Возможно, вы не сможете получить имя функции, потому что они не действительно имеют «имя» как таковое. Точно так же, как ваши переменные не имеют имен. Они просто указывают на объект.

Получение имя не имеет смысла, отчасти из-за следующего примера:

function foo():void 
{ 
    //get function name. 
} 
var bar:Function = foo; 
bar(); 

функция так же, как и любой другой объект/переменной. Какое «имя» будет искать эта функция? "Foo"? или "бар"? Оба foo и bar ссылаются на одну и ту же переменную типа Function.

Лучший способ справиться с этим было бы что-то передать в функцию в качестве аргумента:

function foo(myName:String):void 
{ 
    trace(myName); 
} 

Однако вы можете получить ссылку на текущую функцию с помощью arguments.callee :)

+0

Я нахожу то, о чем вы действительно верите. Даже когда я компилирую версию Flex для версии с отключенными инструкциями по трассировке и не просматривая исходное представление, если не обработана необработанная ошибка, Flash Player предоставит мне последовательность методов _ по имени_, включая ассоциированный класс и соответствующий пакет. Это подсказывает мне, что функция _name_ info определенно закодирована в swf и, следовательно, должна быть доступна каким-то образом. – merv

+3

... разница заключается в том, что стек трассируется «извне», как интроспективная операция, которая позволяет узнать всю иерархию классов и объектов программы, в то время как это невозможно изнутри тела функции. У вас всегда может быть какой-то «пользовательский стек», который отслеживает ваш объект вызовом метода, если вы хотите иметь аналогичную функциональность. – weltraumpirat

+0

@weltraumpirat - Спасибо, что разъяснил это. – merv

5

Я просто сделал это с трассировкой стека, что показывает отладчик Flash Player, когда вызывается необработанная ошибка. Вот моя реализация:

function blah() 
{ 
    var e:Error = new Error(); 
    var s:String = e.getStackTrace(); 
    var functionName:String = s.slice(s.indexOf('/')+1, s.indexOf('(')); 
    trace(functionName); //blah 
} 

Вы, вероятно, нужно сделать синтаксический разбор строки попышнее, если вы хотите сделать это в отдельную функцию. Но имя функции определенно находится в трассировке стека.

Edit: Важная Caveat

AS3 Lang Ref говорит, что метод getStackTrace работает только в отладчике версии Flash Player/AIR, и будет возвращать null иначе. Таким образом, это определенно не решение для развертывания. Сожалею.

+1

Начиная с версии 11.5 и более поздних версий она доступна в версиях без отладчика. Цитата: «Для Flash Player 11.4 и более ранних версий и AIR 3.4 и ранее трассировки стека доступны только в том случае, если код запущен в версии отладчика Flash Player или AIR Debug Launcher (ADL). В версиях, не относящихся к отладчикам этих сред выполнения, вызов этого метода возвращает null.' - http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Error.html –

0

Когда мне нужны идентификаторы для функций для реализации моей системы событий, я не нашел способ получить доступ к name не анонимной функции, переданной в качестве аргумента, поэтому мне пришлось написать оболочку, которая ничего не хранила, кроме Function и его ID

2

чтобы осуществить это в Actionscript 2, который я должен был сделать в последнее время с некоторыми унаследованного кода

function getFunctionName(func:Function):String 
{ 
    for(var prop in this) 
    { 
    if(this[prop] == func) 
    { 
     return prop; 
     break; 
    } 
    } 
} 

И использовать что-то вроде этого

trace(getFunctionName(arguments.callee)); 
Смежные вопросы