actionscript2で呼び出し元の関数の名前を見つける方法はありますか?
-
06-07-2019 - |
質問
actionscript関数(メソッド)では、Functionオブジェクトを返すarguments.callerにアクセスできますが、このFunctionオブジェクトによって表される関数の名前を見つけることができません。 そのtoString()は単に[Function]を返すだけで、それを提供する他の便利なアクセサを見つけることができません... ヘルプ:-/
解決 2
回答が見つかったため、下に貼り付けます。
@fenomas:はい、もちろん、関数は単なるオブジェクトであり、私が探しているのはそれらへの参照の名前です(存在する場合、つまり関数は匿名ではありません)。また、一般的に、これはプログラミングを行うための最良の方法のようには見えないということです;-)しかし、私のシナリオは特別です:Check.checkTrueやChecksなどのメソッドでChecksクラス(C CHECKに似ています)を実装したいです。 checkRefは、チェックが失敗したときに素晴らしいトレースを取得します。トレースはデバッグバージョンでのみ表示され、リリースでは表示されません。
MTASCを使用していますが、以下のコードはMTASCでのみ機能します。また、デバッグ目的でのみ使用し、リリースでは使用しないでください。 手法は、_globalを反復処理し、呼び出し元の関数と等しい関数を見つけることです。これは常に機能するとは限らない(匿名)ハックですが、ほとんどの場合、非常に役立ちます。
39: /**
40: * Checks that cond is true. Use this method to validate that condition
41: * cond holds.
42: * If cond is false, traces a severe message and returns false to indicate
43: * check failure.
44: *
45: * @param cond the contition expected to be true
46: * @param msg the message to emit in case the condition is false.
47: *
48: * @return false is cond is false
49: */
50: public static function checkTrue(cond:Boolean, msg:String):Boolean {
51: if (!cond) {
52: trace("severe", "CHECK FAILED at " +
53: **getFunctionName(arguments.caller)** + ":\n" + msg);
54: }
55: return cond;
56: }
94: /**
95: * Gets the name of the function func.
96: * Warning: Use this only in debug version, not in release
98: *
99: * @return The full package path to the function. null if the function
100: * isn't found.
101: */
102: private static function getFunctionName(func:Function):String {
103: var name:String = getFunctionNameRecursive(func, _global);
108: return name;
109: }
110:
111: /**
112: * Gets the name of the function func by recursively iterating over root.
113: * Warning: Use this only in debug version, not in release
114: */
115: private static function getFunctionNameRecursive(func:Function,
116: root:Object):String {
117: if (!root) {
118: return null;
119: }
120:
121: // Iterate over classes in this package
122: // A class is a function with a prototype object
123: for (var i:String in root) {
124: if (root[i] instanceof Function && root[i].prototype != null) {
125: // Found a class.
126: // Iterate over class static members to see if there's a match
127: for (var f:String in root[i]) {
128: if(root[i][f] == func) {
129: return i + "." + f;
130: }
131: }
132: // Loop over the class's prototype to look for instance methods
133: var instance:Object = root[i].prototype;
134: // Reveal prototype's methods.
135: // Warning: Not to be used in production code!!!
136: // The following line make all the instance attributes visible to the
137: // for-in construct. The "n" value is 8 which means "unhide"
138: // See http://osflash.org/flashcoders/undocumented/assetpropflags
139: // This operation is later undone by setting the "n" to 1 which means
140: // "hide"
141: _global.ASSetPropFlags(instance, null, 8, 1);
142: for (var f:String in instance) {
143: if(instance[f] == func) {
144: return i + "." + f;
145: }
146: }
147: // And hide instance methods again
148: // This line undoes the previous ASSetPropFlags
149: _global.ASSetPropFlags(instance, null, 1, false);
150: }
151: }
152:
153: // Iterate over sub packages. Sub packages have type "object"
154: for (var i:String in root) {
155: if (typeof(root[i]) == "object") {
156: var name:String = getFunctionNameRecursive(func, root[i]);
157: if (name) {
158: return i + "." + name;
159: }
160: }
161: }
162: return null;
163: }
他のヒント
関数は他のようなオブジェクトにすぎません-「名前」がありません;それ自体で;名前を持っているのは、1つ以上の参照を作成できるという意味です。求めているのが、関数が呼び出された参照の名前を取得する方法である場合、それを行う一般的な方法はありません。 (結局、関数は匿名で宣言できます。その場合、関数には名前がまったくありません。)
おそらく、関数の名前を知る必要がある理由を調べ、その名前から導き出そうとしている情報を渡すまたはアクセスする他の方法を見つけ出すことが最善でしょう。追加のパラメーターを渡すことは1つのアプローチかもしれませんが、それはあなたが何をしているかに依存します。
AS2ではなく、私が知る限り AS3のみ。