2

関数の名前を外部から取得する方法はありますか?

Web ページに js スクリプトがあり、それを変更することはできず、読み取るだけであるとします。スクリプトには、オブジェクトと関数を含むオブジェクトが含まれています。「HelloWorld」という名前の関数を見つけたいとしましょう。

firebug では、次のようなスクリプトでこれらのオブジェクトとメソッドをループします。

// Parameter is target object.
function getFunctionNames(obj) {

    // For each objects / functions
    for (var id in obj) {

        // Focus only on functions
        if (typeof(obj[id]) == "function") {

            // Get name of the function.
            // console.log("Function: " + obj[id].toString()); 

            // Code above returns a block of code without the name. Example output:
            // Function: function(name) { alert("Hello World! Hello " + name + "!"); }
            //
            // Expected output would be
            // Function: HelloWorld
        }
    }
}
  • obj[id].toString()は、名前の代わりにコードのブロックを返します。
  • obj[id].nameは空の文字列を返します。無名関数(?)。
  • ターゲット コードを変更できないため、arguments.callee.nameを使用できません。

firebug でオブジェクトや関数をブラウズしたり、ソース コードを読んだりすることもできますが、Javascript でそれを行う方法を探しています

編集

実際の例については、Youtubeにアクセスして、Javascript を介して「yt」オブジェクトから関数「setMsg()」の名前を取得してみてください。

編集2

私が探していたものにちょっと近いというサイモンの答えを受け入れます。関数名ではなく、変数名を探していたようです。答えは元の問題では役に立ちませんでしたが、元の質問には確かに答えました。Paul Draper のコメントのおかげで、正しい方向に進むことができました。

ありがとう!

4

2 に答える 2

2

使用するobj.name

関数arguments.calleeを返すことに注意してください。はすべての関数のプロパティです (ただし、無名関数では空です)。そのため、機能します。namearguments.callee.name

これは、Webkit (Chrome および Safari)、Firefox、およびおそらくその他のもので機能します。IE では機能しません: function.name は IE ではサポートされていません。

于 2013-11-03T00:31:13.480 に答える
1

""前述のように、関数には、匿名関数であることから得られる以外の固有の名前はありません。ただし、一部のブラウザー (Firefox、おそらく Chrome、おそらく他のブラウザー) は、エラー スタック トレースを支援するために、宣言された関数の名前を把握するために、限定的な形式の静的分析を実行します。setMsg例外をスローしてから解析することで、比較的クロスブラウザーの方法でアクセスできますexc.stack

// cheat with .% in Firebug; there might be other ways of doing this, I dunno:
yt.setMsg.%m.za.__defineSetter__('a', function() { throw new Error(); });

try { yt.setMsg('a', 'a'); }
catch(e) { alert(e.stack.split('\n')[2].split('@')[0]); }

... 一方で、これはかなりひどいハックであり、関連する実際の関数に依存します (関数を知っている場合は、おそらくその名前を既に知っているでしょう)。関数内から実行すると、もう少し確実に機能します。

Firefox だけに制限し、デバッグ目的でこれを行っている場合は、それに到達するためのより良い方法があります。about:config で true に設定devtools.chrome.enabledし、スクラッチパッドを開き (Shift+F4)、environment: browser に設定して、次を実行します。

Components.utils.import("resource://gre/modules/jsdebugger.jsm");
window.addDebuggerToGlobal(window);

dbg = new Debugger();
dw = dbg.addDebuggee(content);

f = content.wrappedJSObject.yt.setMsg;
name = dw.makeDebuggeeValue(f).displayName;

dbg.removeDebuggee(content);

alert(name);

どちらの場合も、"setMsg" ではなく "m.ya" を警告することに注意してください。実際、これは関数が最初に として宣言されたためm.ya = function() { ...; }です。ブラウザの観点から、「setMsg」が望ましい名前である理由はありません。

于 2013-11-03T12:00:09.600 に答える