2011-12-14 6 views

答えて

3

一般的に、 JavaScriptは、変数定義や呼び出しスタックのイントロスペクションに信頼できる方法を提供しません。あなたはそれを歩いて、ソースコードを抽出することができるように

arguments.calleearguments.callerは、限り何の再帰呼び出しが存在しないとして、コールスタック上の関数のセットにイントロスペクションを提供します。しかし、それは

fが呼び出される
function defeatArgumentsCaller(f, args, called) { 
    if (!called) { return defeatArgumentsCaller(f, args, true); } 
    return f.apply(args); 
} 

function f() { 
    defeatArgumentsCaller(g, []); 
} 

で敗北することができ、gは、それがarguments.callerを見て、fで呼ばれたことを判断することはできません。

function g() { 
    var fn = arguments.callee; 
    while (true) { 
    alert(fn.name); 
    var caller = fn.caller; 
    // defaultArgumentsCaller is itself, not f. 
    if (!caller || caller == fn) { break; } 
    fn = caller; 
    } 
} 

これらは、定義されたシンボルのセットに対してイントロスペクションを許可しません。 withまたはcatchを介して導入されたものので、コールスタックと機能のソースコードを調べることによって

function f(o) { 
    try { 
    throw null; 
    } catch (e) { 
    with (o) { 
     ... 
    } 
    } 
} 

...で利用可能なローカル変数を列挙しようとすると、いくつかの定義されたシンボルを欠場します。

コールスタックは、クロージャのスタックとも異なります。例えば、counter以来示唆しているコールスタックより利用できるより多くのシンボルを持っている状況で

function counter() { 
    var n; 
    return function (f) { return f(n++); }; 
} 

counter()(eval); 

eval実行で呼び出された時点evalにコールスタック上ではありません。

Rhinoは、現在のスタックフレームに名前を列挙するために使用することができ、あなたがgetPrototypeを経由して高いスタックフレームまで歩くことができるgetIds方法を公開しScriptableとして現在のスコープへのアクセスを可能にします。

+0

これを確認する必要があります。アンパサンドは言った、それは全文を与えます。それがなければ、私はRhinoの方法をチェックします。あなたもありがとう。 – xamiro

+0

@ mc007、あなたは100%のソリューションは必要ないかもしれませんが、そのソリューションは再帰的な外部関数のために失敗します。 –

+0

+1。大きな説明と例。私が書いたり読んだコードの85%については、 'arguments.callee'と' arguments.caller'が動作します。 – ampersand

4

argumentsオブジェクトが現在実行中の関数を指すメンバーcalleeを有する:

function example(){ 
    console.log(arguments.callee.toString()) 
} 

意志出力完全な関数定義。したがって、これは内部コードだけではなく、周囲のfunction(){...}の定義を含みます。

+0

かわいいです、私はこのやり方でちょっと遊ぶ必要があります。ありがとう! – xamiro

+0

これは1レベル上に進むだけです。 –

+0

'arguments.caller'はもう1つ上のレベルになります。 – ampersand

関連する問題